Bound Process payload sizes and capture rendered order feedback
Box the optional Process menu context and changed order command without changing identity or command semantics. Add opt-in actual WGPU readbacks to the split-event OA/SA reorder evaluator. Strict all-target lint, format and affected desktop paths pass; native acceptance follows.
This commit is contained in:
@@ -245,7 +245,7 @@ impl Graph<'_> {
|
||||
};
|
||||
let mut request = crate::model_menu::Request::object(object, pointer);
|
||||
request.selection_target = Some(Box::new(target));
|
||||
request.process = Some(context);
|
||||
request.process = Some(Box::new(context));
|
||||
return Some(
|
||||
Action::publish(Message::Menu(crate::model_menu::Event::Open(request)))
|
||||
.and_capture(),
|
||||
|
||||
@@ -127,14 +127,16 @@ fn group_drag_uses_midpoint_anchors_and_original_order_and_singleton_after_gap()
|
||||
};
|
||||
assert_eq!(snapshot, graph.selection.clone().unwrap());
|
||||
assert_eq!(destination, Destination::After(f.nodes[1]));
|
||||
let Plan::Change(Command::SetSteps(owner, steps)) =
|
||||
Prepared::new(&f.p, f.owner, snapshot.targets())
|
||||
.unwrap()
|
||||
.plan(destination)
|
||||
.unwrap()
|
||||
let Plan::Change(command) = Prepared::new(&f.p, f.owner, snapshot.targets())
|
||||
.unwrap()
|
||||
.plan(destination)
|
||||
.unwrap()
|
||||
else {
|
||||
panic!("changed steps");
|
||||
};
|
||||
let Command::SetSteps(owner, steps) = *command else {
|
||||
panic!("expected SetSteps");
|
||||
};
|
||||
assert_eq!(owner, f.owner);
|
||||
assert_eq!(steps, vec![f.nodes[1], f.nodes[0], f.nodes[2]]);
|
||||
}
|
||||
@@ -302,7 +304,7 @@ fn qualified_occurrences_and_visible_preview_links_keep_exact_invocation_paths()
|
||||
matches!(press(&graph, &mut input, at), Some(Message::DiagramSelection(SelectionEvent::Choose(_, target, Choice::Toggle))) if target == expected)
|
||||
);
|
||||
assert!(
|
||||
matches!(send(&graph, &mut input, canvas::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)), at), Some(Message::Menu(crate::model_menu::Event::Open(request))) if request.selection_target.as_deref() == Some(&expected) && request.process == graph.interaction.map(|(context,_,_)| context))
|
||||
matches!(send(&graph, &mut input, canvas::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)), at), Some(Message::Menu(crate::model_menu::Event::Open(request))) if request.selection_target.as_deref() == Some(&expected) && request.process.as_deref().copied() == graph.interaction.map(|(context,_,_)| context))
|
||||
);
|
||||
}
|
||||
assert_ne!(targets[0], targets[1]);
|
||||
|
||||
@@ -365,7 +365,7 @@ fn direct_process_reconnect_delete_and_reorder_preserve_other_paths_and_sources(
|
||||
else {
|
||||
panic!("changed order");
|
||||
};
|
||||
let reordered = execute_batch(&f.p, &[command]).unwrap();
|
||||
let reordered = execute_batch(&f.p, &[*command]).unwrap();
|
||||
assert_eq!(reordered.elements[&f.owner].steps().unwrap()[0], f.nodes[2]);
|
||||
assert_eq!(reordered.relations, f.p.relations);
|
||||
assert!(direct::reorder(&f.p, f.owner, f.nodes[0], f.nodes[1]).is_err());
|
||||
|
||||
@@ -11,7 +11,7 @@ pub(crate) enum Destination {
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Plan {
|
||||
Noop,
|
||||
Change(Command),
|
||||
Change(Box<Command>),
|
||||
}
|
||||
|
||||
/// Captured semantic facts only: no project clone, projection or routed scene.
|
||||
@@ -156,7 +156,9 @@ impl Prepared {
|
||||
"This reorder would change process columns; the whole move was refused.".into(),
|
||||
);
|
||||
}
|
||||
Ok(Plan::Change(Command::SetSteps(self.owner, ordered)))
|
||||
Ok(Plan::Change(Box::new(Command::SetSteps(
|
||||
self.owner, ordered,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ fn changed(project: &Project, owner: Id, targets: &[Target], drop: Destination)
|
||||
let Plan::Change(command) = plan(project, owner, targets, drop).unwrap() else {
|
||||
panic!("Expected an actual order change");
|
||||
};
|
||||
assert!(matches!(&command, Command::SetSteps(id, _) if *id == owner));
|
||||
command
|
||||
assert!(matches!(command.as_ref(), Command::SetSteps(id, _) if *id == owner));
|
||||
*command
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -395,7 +395,7 @@ fn process_group_columns_parallel_links_keep_exact_ranks_and_relation_records()
|
||||
let Plan::Change(command) = prepared.plan(Destination::Before(a)).unwrap() else {
|
||||
panic!("Expected move");
|
||||
};
|
||||
let result = execute_batch(&project, &[command]).unwrap();
|
||||
let result = execute_batch(&project, &[*command]).unwrap();
|
||||
assert_eq!(
|
||||
result.elements[&owner].steps().unwrap(),
|
||||
&vec![b, u, c, v, a]
|
||||
|
||||
@@ -192,6 +192,47 @@ async fn production_process_multiselect_reverse_click_group_drop_has_one_history
|
||||
let snapshot = app.multiselect_snapshot().unwrap();
|
||||
let source = app.document.bundle().clone();
|
||||
let camera = (app.behavior.topology.pan, app.behavior.topology.zoom);
|
||||
// Reuse the existing opt-in raw WGPU evidence convention. These are
|
||||
// actual production-tree pixels, not a reconstructed preview image.
|
||||
let record_feedback = |stage: &str, mounted: &mut Mounted, app: &App, cursor: Point| {
|
||||
let Some(path) = std::env::var_os("ARCADIA_RENDER_EVIDENCE_DIR") else {
|
||||
return;
|
||||
};
|
||||
let path = std::path::PathBuf::from(path);
|
||||
std::fs::create_dir_all(&path).unwrap();
|
||||
let name = format!("process-{layer:?}-{stage}");
|
||||
let pixels = mounted.pixels_at(app, mouse::Cursor::Available(cursor));
|
||||
let width = app.window_size.width as u32;
|
||||
let height = app.window_size.height as u32;
|
||||
assert_eq!(pixels.len(), width as usize * height as usize * 4);
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
.open(path.join(format!("{name}.rgba")))
|
||||
.unwrap();
|
||||
std::io::Write::write_all(&mut file, &pixels).unwrap();
|
||||
let metadata = serde_json::json!({
|
||||
"width": width, "height": height, "format": "RGBA8",
|
||||
"stage": stage, "layer": format!("{layer:?}"),
|
||||
"canvas": [bounds.x, bounds.y, bounds.width, bounds.height],
|
||||
"cursor": [cursor.x, cursor.y], "scale": scale,
|
||||
"camera": [app.behavior.topology.pan.x, app.behavior.topology.pan.y],
|
||||
"selectionCount": snapshot.targets().len(),
|
||||
"selection": format!("{snapshot:?}"),
|
||||
"source": app.document.bundle(),
|
||||
});
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
.open(path.join(format!("{name}.json")))
|
||||
.unwrap();
|
||||
std::io::Write::write_all(&mut file, &serde_json::to_vec_pretty(&metadata).unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(app.document.bundle(), &source);
|
||||
assert_eq!(app.multiselect_snapshot().unwrap(), snapshot);
|
||||
assert!(!app.document.can_undo());
|
||||
};
|
||||
record_feedback("before-press", &mut mounted, &app, points[1]);
|
||||
let pressed = mounted
|
||||
.batch(
|
||||
&mut app,
|
||||
@@ -235,6 +276,7 @@ async fn production_process_multiselect_reverse_click_group_drop_has_one_history
|
||||
(app.behavior.topology.pan, app.behavior.topology.zoom),
|
||||
camera
|
||||
);
|
||||
record_feedback("after-motion", &mut mounted, &app, points[2]);
|
||||
let messages = mounted
|
||||
.batch(
|
||||
&mut app,
|
||||
|
||||
Reference in New Issue
Block a user