Selection feedback and origin: hover and selected highlights (theme tokens), origin planes/axes/point at a fixed screen size with browser eye toggles, click-to-pick sketch planes and faces with camera animation (Finish Sketch returns), multi-select dialog inputs with pre-selection, tangent chains and face-to-edges, window/crossing box selection, shell/draft/mirror/hole dialogs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
059909fb05
commit
97e73b0935
20 files changed
+1907
-518
No files matched your search
@@ -29,6 +29,24 @@ fn eye(ui: &mut egui::Ui, visible: bool) -> bool {
|
||||
resp.on_hover_text(if visible { "Hide" } else { "Show" }).clicked()
|
||||
}
|
||||
|
||||
/// A browser click on a plane or axis: it goes to the open dialog's input if that takes it,
|
||||
/// otherwise it becomes the selection.
|
||||
fn pick_from_browser(app: &mut SolveApp, x: Sel) {
|
||||
let hit = match &x {
|
||||
Sel::Plane { name } => crate::viewport::Hit::Plane { name: name.clone(), point: solvecraft_engine::geom::Vec3::ZERO },
|
||||
Sel::Axis { name } => crate::viewport::Hit::Axis { name: name.clone() },
|
||||
_ => return,
|
||||
};
|
||||
if let Some(mut d) = app.dialog.take() {
|
||||
if let Some(sel) = d.candidate(&app.session, &hit) {
|
||||
d.pick(&app.session, sel);
|
||||
}
|
||||
app.dialog = Some(d);
|
||||
return;
|
||||
}
|
||||
let _ = app.run("select.set", json!({ "items": [x] }));
|
||||
}
|
||||
|
||||
pub fn browser(app: &mut SolveApp, ui: &mut egui::Ui) {
|
||||
let t = Tokens::get();
|
||||
egui::Panel::left("sc_browser")
|
||||
@@ -53,16 +71,38 @@ pub fn browser(app: &mut SolveApp, ui: &mut egui::Ui) {
|
||||
app.start("ChangeParameterCommand");
|
||||
}
|
||||
});
|
||||
egui::CollapsingHeader::new("Origin").default_open(false).show(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if eye(ui, app.ui.show_origin) {
|
||||
app.ui.show_origin = !app.ui.show_origin;
|
||||
}
|
||||
ui.label("O, X, Y, Z");
|
||||
});
|
||||
for p in ["XY", "XZ", "YZ"] {
|
||||
row(ui, "plane", p, None, false);
|
||||
ui.horizontal(|ui| {
|
||||
if eye(ui, app.ui.show_origin) {
|
||||
app.ui.show_origin = !app.ui.show_origin;
|
||||
}
|
||||
egui::CollapsingHeader::new("Origin").default_open(false).show(ui, |ui| {
|
||||
let items = [("O", "point", "Origin point"), ("X", "axis", "X axis"), ("Y", "axis", "Y axis"), ("Z", "axis", "Z axis")]
|
||||
.into_iter()
|
||||
.chain([("XY", "plane", "XY"), ("XZ", "plane", "XZ"), ("YZ", "plane", "YZ")]);
|
||||
for (key, icon, label) in items {
|
||||
let visible = !app.ui.hidden_origin.iter().any(|h| h == key);
|
||||
let sel = match icon {
|
||||
"plane" => Some(Sel::Plane { name: key.into() }),
|
||||
"axis" => Some(Sel::Axis { name: key.into() }),
|
||||
_ => None,
|
||||
};
|
||||
let selected = sel.as_ref().is_some_and(|x| app.session.selection.contains(x));
|
||||
ui.horizontal(|ui| {
|
||||
if eye(ui, visible) {
|
||||
if visible {
|
||||
app.ui.hidden_origin.push(key.into());
|
||||
} else {
|
||||
app.ui.hidden_origin.retain(|h| h != key);
|
||||
}
|
||||
}
|
||||
if row(ui, icon, label, None, selected).clicked()
|
||||
&& let Some(x) = &sel
|
||||
{
|
||||
pick_from_browser(app, x.clone());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
egui::CollapsingHeader::new(format!("Bodies ({})", st.bodies.len())).default_open(true).show(ui, |ui| {
|
||||
for b in &st.bodies {
|
||||
|
||||
Reference in new issue
Block a user