forked from 1b-agent/fieldcraft-upstream
UI: seeds as ticks along their edges, Mesh › Seeds, and seeding the selection
A seed draws a tick at each node it puts on its edge, so a bias shows as ticks crowding toward an end. The browser lists the seeds under Mesh; a click selects the seeded edge. The Seed Edges form takes the selected edges with Use selection. The toolbar entry is ready (its icon renamed with it). Part of #230. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
e8cada94d0
commit
8df4ea040c
9 files changed
+134
-4
No files matched your search
@@ -296,6 +296,20 @@ enum Act {
|
||||
ShowResult(String),
|
||||
}
|
||||
|
||||
/// A seed in a few words: `8 exact`, `2.5 min, bias 4 end`.
|
||||
fn seed_note(s: &fieldcraft_model::Seed) -> String {
|
||||
let what = match s.divisions {
|
||||
fieldcraft_model::Divisions::Count(n) => format!("{n}"),
|
||||
fieldcraft_model::Divisions::Size(h) => format!("size {h}"),
|
||||
};
|
||||
let bias = s.bias.map(|b| format!(", bias {} {}", b.ratio, json_name(&b.toward))).unwrap_or_default();
|
||||
format!("{what} {}{bias}", s.constraint.name())
|
||||
}
|
||||
|
||||
fn json_name<T: serde::Serialize>(v: &T) -> String {
|
||||
serde_json::to_value(v).ok().and_then(|v| v.as_str().map(str::to_string)).unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn browser(app: &mut ModelApp, ui: &mut egui::Ui) {
|
||||
let t = Tokens::get(app.ui.dark);
|
||||
let mut acts: Vec<Act> = Vec::new();
|
||||
@@ -485,6 +499,40 @@ fn rows(app: &mut ModelApp, ui: &mut egui::Ui, acts: &mut Vec<Act>) {
|
||||
&Row { depth: 2, swatch: Some(t.element(kind)), label: kind.name(), note: Some(format!("{n}")), ..Default::default() },
|
||||
);
|
||||
}
|
||||
// Edge seeds: a click selects the seeded edge in the viewport.
|
||||
let seeds: Vec<(fieldcraft_model::GeometryRef, String)> = app.session.model.seeds().iter().map(|s| (s.edge.clone(), seed_note(s))).collect();
|
||||
if !seeds.is_empty() {
|
||||
let r = draw_row(
|
||||
app,
|
||||
ui,
|
||||
egui::Id::new("fc_row_seeds"),
|
||||
&Row {
|
||||
depth: 2,
|
||||
fold: Some(open(app, "seeds")),
|
||||
icon: Some("mesh.seed.edge"),
|
||||
label: "Seeds",
|
||||
note: Some(format!("{}", seeds.len())),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
if r.fold || r.clicked {
|
||||
acts.push(Act::Fold("seeds".into()));
|
||||
}
|
||||
if open(app, "seeds") {
|
||||
for (i, (edge, note)) in seeds.into_iter().enumerate() {
|
||||
let label = format!("{} · {}", edge.body, edge.entity.name().unwrap_or_default());
|
||||
let r = draw_row(
|
||||
app,
|
||||
ui,
|
||||
egui::Id::new(("fc_row_seed", i)),
|
||||
&Row { depth: 3, label: &label, note: Some(note), ..Default::default() },
|
||||
);
|
||||
if r.clicked {
|
||||
app.select([crate::selection::Item::Geometry(edge)], crate::selection::Mode::Replace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Definitions.
|
||||
let groups: [(&str, &str, &[Def]); 7] = [
|
||||
|
||||
Reference in new issue
Block a user