ui: pick vertices, points and cells from the viewport

- Select: Vertices picks the design's B-rep vertices (meshed or not), and
  a selected vertex is marked (#346).
- Use selection on Datum Point (vertex, edge, face, or a hole's centre)
  and Reference Point (geometry.centre: a hole's centre, a vertex, nodes)
  (#346, #351).
- Partitioned Mesh: Use selection takes the picked bodies as cells; the
  cell list has All, None and Invert; hovering a cell's row (or its method
  row) highlights the cell in the viewport (#344).
- Rigid Wall's form takes its set from the selection; the Interactions
  branch lists the explicit steps' rigid walls, each opening its step
  (#350).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 09:27:39 -04:00
1 parent 1372094f8a
commit a09e3c856b
5 files changed
+143 -8

No files matched your search

+21
View File
@@ -237,6 +237,8 @@ pub struct PickState {
pub dragging: Option<(egui::Pos2, egui::Pos2)>,
/// Where the pointer was when the hover was worked out (window points).
pub hover_at: Option<egui::Pos2>,
/// The hover is a body whose row in a command form is under the pointer, not the viewport's.
pub form_hover: bool,
/// Bumped whenever the selection changes, and whenever the hover does.
generation: u64,
hover_generation: u64,
@@ -957,6 +959,7 @@ impl ModelApp {
name: body.name.clone(),
faces: body.faces().iter().map(|f| f.name.clone()).collect(),
edges: body.edge_names(&mesh),
vertices: body.vertex_names(&mesh).into_iter().map(|v| (v.name, v.point.into())).collect(),
};
Some((names, mesh))
})
@@ -980,6 +983,7 @@ impl ModelApp {
name: s.name.clone(),
faces: (0..s.faces).map(|f| f.to_string()).collect(),
edges: Vec::new(),
vertices: Vec::new(),
});
}
let was_empty = self.display.1.bounds.is_empty();
@@ -1423,6 +1427,23 @@ impl ModelApp {
selection::Target::Edges => {
selection::with_edges(&params, &self.pick.selection).ok_or("no edge is selected: pick edges with Select: Edges")?
}
selection::Target::Position | selection::Target::DatumPoint => {
// A query that fills the form: it changes nothing and has no reply panel of its own.
let centre = self.session.execute("geometry.centre", &self.pick.selection.params()).map_err(|e| e.to_string())?;
let mut out = params.as_object().cloned().unwrap_or_default();
if target == selection::Target::Position {
out.insert("xyz".into(), centre.get("point").cloned().unwrap_or(Value::Null));
} else {
out.insert("by".into(), selection::datum_point_by(&self.pick.selection, &centre));
}
Value::Object(out)
}
selection::Target::Bodies => {
let bodies = selection::bodies(&self.pick.selection).ok_or("no geometry is selected: pick cells with Select: Bodies")?;
let mut out = params.as_object().cloned().unwrap_or_default();
out.insert("bodies".into(), json!(bodies));
Value::Object(out)
}
selection::Target::Set | selection::Target::TargetSet => {
let base = params.get("name").and_then(Value::as_str).map(|n| format!("{n}-set"));
let set = self.selection_set(base.as_deref())?;