Navigation bar: Look At (selected face or plane, else the active sketch) and visual style (shaded with edges, shaded, wireframe; kept between runs); F6 fits the view
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
9c03f4bf32
commit
888ac0f5c4
4 files changed
+50
-5
No files matched your search
@@ -183,6 +183,15 @@ pub fn paint(p: &Painter, r: Rect, name: &str, ink: Color32, fill: Color32, acce
|
||||
pen.poly(&[(3.0, 7.0), (9.0, 10.0), (9.0, 17.0), (3.0, 17.0)], pen.fill, ink);
|
||||
pen.poly(&[(21.0, 7.0), (15.0, 10.0), (15.0, 17.0), (21.0, 17.0)], Color32::TRANSPARENT, a);
|
||||
}
|
||||
"lookat" => {
|
||||
pen.poly(&[(4.0, 6.0), (16.0, 6.0), (16.0, 18.0), (4.0, 18.0)], pen.fill, ink);
|
||||
pen.arrow((22.0, 12.0), (13.0, 12.0), a);
|
||||
}
|
||||
"style" => {
|
||||
pen.poly(&[(12.0, 3.0), (20.0, 7.5), (12.0, 12.0), (4.0, 7.5)], pen.fill, ink);
|
||||
pen.poly(&[(4.0, 7.5), (12.0, 12.0), (12.0, 21.0), (4.0, 16.5)], a, ink);
|
||||
pen.poly(&[(12.0, 12.0), (20.0, 7.5), (20.0, 16.5), (12.0, 21.0)], Color32::TRANSPARENT, ink);
|
||||
}
|
||||
"sun" => {
|
||||
pen.circle(12.0, 12.0, 4.5, a, ink);
|
||||
for i in 0..8 {
|
||||
|
||||
@@ -61,6 +61,8 @@ pub struct UiState {
|
||||
pub pick_off: Vec<String>,
|
||||
/// A click on a face picks its whole body.
|
||||
pub pick_bodies: bool,
|
||||
/// 0: shaded with edges, 1: shaded, 2: wireframe.
|
||||
pub visual_style: u8,
|
||||
/// Sketches hidden one by one, and finished sketches shown although a feature uses them.
|
||||
pub hidden_sketches: Vec<u64>,
|
||||
pub shown_sketches: Vec<u64>,
|
||||
@@ -86,6 +88,7 @@ impl Default for UiState {
|
||||
dark: true,
|
||||
pick_off: Vec::new(),
|
||||
pick_bodies: false,
|
||||
visual_style: 0,
|
||||
hidden_sketches: Vec::new(),
|
||||
shown_sketches: Vec::new(),
|
||||
hidden_profiles: Vec::new(),
|
||||
@@ -184,6 +187,7 @@ impl SolveApp {
|
||||
"perspective": self.ui.perspective,
|
||||
"pick_bodies": self.ui.pick_bodies,
|
||||
"auto_project": self.session.auto_project,
|
||||
"visual_style": self.ui.visual_style,
|
||||
})
|
||||
.to_string()
|
||||
}
|
||||
@@ -207,6 +211,9 @@ impl SolveApp {
|
||||
if let Some(a) = flag("auto_project") {
|
||||
self.session.auto_project = a;
|
||||
}
|
||||
if let Some(s) = v.get("visual_style").and_then(Value::as_u64) {
|
||||
self.ui.visual_style = u8::try_from(s.min(2)).unwrap_or(0);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_control(mut self, rx: Receiver<ControlRequest>) -> Self {
|
||||
|
||||
@@ -406,6 +406,7 @@ pub fn shortcuts(app: &mut SolveApp, ctx: &egui::Context) {
|
||||
}
|
||||
}
|
||||
Key::S => app.ui.palette_open = true,
|
||||
Key::F6 => app.animate_view("fit"),
|
||||
Key::Delete | Key::Backspace => crate::viewport::delete_selection(app),
|
||||
_ => {
|
||||
let name = format!("{k:?}");
|
||||
|
||||
@@ -155,6 +155,7 @@ fn scene_key(app: &SolveApp) -> u64 {
|
||||
let mut h = std::collections::hash_map::DefaultHasher::new();
|
||||
app.session.revision.hash(&mut h);
|
||||
app.ui.show_grid.hash(&mut h);
|
||||
app.ui.visual_style.hash(&mut h);
|
||||
app.ui.show_sketches.hash(&mut h);
|
||||
app.ui.hidden_bodies.hash(&mut h);
|
||||
app.ui.hidden_sketches.hash(&mut h);
|
||||
@@ -210,7 +211,13 @@ fn build_scene(app: &SolveApp) -> GpuScene {
|
||||
let base = s.doc.materials.get(&b.name).and_then(|m| crate::theme::material_color(m)).unwrap_or(tk.body);
|
||||
let col = if faded { c4(base.gamma_multiply(0.35)) } else { c4(base) };
|
||||
let m = b.mesh();
|
||||
for t in &m.triangles {
|
||||
let (shaded, edges) = match app.ui.visual_style {
|
||||
1 => (true, false),
|
||||
2 => (false, true),
|
||||
_ => (true, true),
|
||||
};
|
||||
let edge_col = if shaded { c4(tk.body_edge) } else { c4(tk.text) };
|
||||
for t in m.triangles.iter().filter(|_| shaded) {
|
||||
for k in t {
|
||||
let i = *k as usize;
|
||||
if let (Some(p), Some(n)) = (m.positions.get(i), m.normals.get(i)) {
|
||||
@@ -222,12 +229,12 @@ fn build_scene(app: &SolveApp) -> GpuScene {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ei, e) in m.edges.iter().enumerate() {
|
||||
for (ei, e) in m.edges.iter().enumerate().filter(|_| edges) {
|
||||
if m.seams.get(ei).copied().unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
for w in e.windows(2) {
|
||||
sc.line(w[0].to_f32(), w[1].to_f32(), c4(tk.body_edge), 1.3, false);
|
||||
sc.line(w[0].to_f32(), w[1].to_f32(), edge_col, 1.3, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1483,15 +1490,34 @@ fn point_in_poly(p: Pos2, poly: &[Pos2]) -> bool {
|
||||
}
|
||||
|
||||
/// Navigation bar (bottom centre).
|
||||
/// Turn the view to face the selected planar face or plane, else the active sketch.
|
||||
pub fn look_at_selection(app: &mut SolveApp) {
|
||||
let target = app.session.selection.iter().find_map(|s| match s {
|
||||
Sel::Face { body, index, point } => crate::dialogs::planar_face(&app.session, body, *index).map(|(_, n)| (*point, n)),
|
||||
Sel::Plane { name } => solvecraft_engine::geom::Plane::named(name).map(|p| (p.origin, p.normal())),
|
||||
_ => None,
|
||||
});
|
||||
match target {
|
||||
Some((p, n)) => {
|
||||
let mut to = app.cam.looking_from(n);
|
||||
to.target = p;
|
||||
app.animate_to(to);
|
||||
}
|
||||
None => crate::dialogs::look_at_sketch(app),
|
||||
}
|
||||
}
|
||||
|
||||
fn nav_bar(app: &mut SolveApp, ui: &mut egui::Ui, rect: Rect) {
|
||||
let t = Tokens::get();
|
||||
let items: [(&str, &str); 7] = [
|
||||
let items: [(&str, &str); 9] = [
|
||||
("orbit", "Orbit (drag; or Shift+middle / right drag)"),
|
||||
("pan", "Pan (drag; or middle drag)"),
|
||||
("zoom", "Zoom (drag; or wheel)"),
|
||||
("fit", "Fit"),
|
||||
("fit", "Fit (F6)"),
|
||||
("lookat", "Look At the selected face or plane (or the active sketch)"),
|
||||
("home", "Home view"),
|
||||
("perspective", "Perspective / orthographic"),
|
||||
("style", "Visual style: shaded with edges, shaded, wireframe"),
|
||||
("settings", "Grid on/off"),
|
||||
];
|
||||
let w = items.len() as f32 * 30.0 + 10.0;
|
||||
@@ -1521,6 +1547,8 @@ fn nav_bar(app: &mut SolveApp, ui: &mut egui::Ui, rect: Rect) {
|
||||
"zoom" => app.viewport.nav = toggle(NavMode::Zoom, app.viewport.nav),
|
||||
"fit" => app.animate_view("fit"),
|
||||
"home" => app.animate_view("home"),
|
||||
"lookat" => look_at_selection(app),
|
||||
"style" => app.ui.visual_style = (app.ui.visual_style + 1) % 3,
|
||||
"perspective" => app.ui.perspective = !app.ui.perspective,
|
||||
_ => app.ui.show_grid = !app.ui.show_grid,
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user