Continuous orbit (navigation bar): the view turns about the vertical until the next click or key
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
1970b8c680
commit
8fa566af33
2 files changed
+34
-1
No files matched your search
@@ -421,6 +421,14 @@ pub fn paint(p: &Painter, r: Rect, name: &str, ink: Color32, fill: Color32, acce
|
|||||||
pen.arrow((17.0, 17.5), (19.6, 14.5), a);
|
pen.arrow((17.0, 17.5), (19.6, 14.5), a);
|
||||||
pen.dot(12.0, 12.0, ink);
|
pen.dot(12.0, 12.0, ink);
|
||||||
}
|
}
|
||||||
|
"spin" => {
|
||||||
|
// A turntable: an ellipse with an arrow running round it, a post in the middle.
|
||||||
|
let pts: Vec<Pos2> = (0..=28).map(|i| 0.2 + i as f32 / 28.0 * 5.6).map(|t| pen.at(12.0 + 9.0 * t.cos(), 16.0 + 3.5 * t.sin())).collect();
|
||||||
|
p.add(Shape::line(pts, Stroke::new(pen.w, ink)));
|
||||||
|
pen.arrow((17.0, 19.0), (20.5, 17.0), a);
|
||||||
|
pen.line(&[(12.0, 15.5), (12.0, 4.0)], ink);
|
||||||
|
pen.poly(&[(9.0, 9.0), (15.0, 9.0), (15.0, 4.0), (9.0, 4.0)], Color32::TRANSPARENT, ink);
|
||||||
|
}
|
||||||
"pan" => {
|
"pan" => {
|
||||||
for (dx, dy) in [(0.0, -1.0), (0.0, 1.0), (-1.0, 0.0), (1.0, 0.0)] {
|
for (dx, dy) in [(0.0, -1.0), (0.0, 1.0), (-1.0, 0.0), (1.0, 0.0)] {
|
||||||
pen.arrow((12.0 + 3.0 * dx, 12.0 + 3.0 * dy), (12.0 + 9.0 * dx, 12.0 + 9.0 * dy), ink);
|
pen.arrow((12.0 + 3.0 * dx, 12.0 + 3.0 * dy), (12.0 + 9.0 * dx, 12.0 + 9.0 * dy), ink);
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ pub struct ViewportState {
|
|||||||
pub hover_bodies: Vec<String>,
|
pub hover_bodies: Vec<String>,
|
||||||
/// The model point an orbit turns around (Preferences: orbit around the cursor).
|
/// The model point an orbit turns around (Preferences: orbit around the cursor).
|
||||||
pub orbit_pivot: Option<Vec3>,
|
pub orbit_pivot: Option<Vec3>,
|
||||||
|
/// Continuous orbit: the view turns about the vertical until the next click or key.
|
||||||
|
pub spin: bool,
|
||||||
pub build_ms: f64,
|
pub build_ms: f64,
|
||||||
/// The right-click menu, open at this screen position.
|
/// The right-click menu, open at this screen position.
|
||||||
pub context_menu: Option<Pos2>,
|
pub context_menu: Option<Pos2>,
|
||||||
@@ -1221,6 +1223,23 @@ pub fn show(app: &mut SolveApp, ui: &mut egui::Ui) {
|
|||||||
if !dragging {
|
if !dragging {
|
||||||
app.viewport.orbit_pivot = None;
|
app.viewport.orbit_pivot = None;
|
||||||
}
|
}
|
||||||
|
if app.viewport.spin {
|
||||||
|
// A click on the navigation bar (its own button) is not a stop.
|
||||||
|
let bar = Rect::from_center_size(pos2(rect.center().x, rect.bottom() - 22.0), vec2(320.0, 30.0));
|
||||||
|
let (pressed, key, dt) = ui.input(|i| {
|
||||||
|
(
|
||||||
|
i.pointer.any_pressed() && inside && !i.pointer.press_origin().is_some_and(|p| bar.contains(p)),
|
||||||
|
i.events.iter().any(|e| matches!(e, egui::Event::Key { pressed: true, .. })),
|
||||||
|
i.stable_dt,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
if pressed || key || dragging {
|
||||||
|
app.viewport.spin = false;
|
||||||
|
} else {
|
||||||
|
app.cam.orbit(f64::from(dt.min(0.1)) * 30.0, 0.0);
|
||||||
|
ui.ctx().request_repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
if !app.cam.is_valid() {
|
if !app.cam.is_valid() {
|
||||||
app.cam = Camera::default();
|
app.cam = Camera::default();
|
||||||
app.fit_view();
|
app.fit_view();
|
||||||
@@ -1897,8 +1916,9 @@ pub fn look_at_selection(app: &mut SolveApp) {
|
|||||||
|
|
||||||
fn nav_bar(app: &mut SolveApp, ui: &mut egui::Ui, rect: Rect) {
|
fn nav_bar(app: &mut SolveApp, ui: &mut egui::Ui, rect: Rect) {
|
||||||
let t = Tokens::get();
|
let t = Tokens::get();
|
||||||
let items: [(&str, &str); 9] = [
|
let items: [(&str, &str); 10] = [
|
||||||
("orbit", "Orbit (drag; or Shift+middle / right drag)"),
|
("orbit", "Orbit (drag; or Shift+middle / right drag)"),
|
||||||
|
("spin", "Continuous orbit (stops at the next click or key)"),
|
||||||
("pan", "Pan (drag; or middle drag)"),
|
("pan", "Pan (drag; or middle drag)"),
|
||||||
("zoom", "Zoom (drag; or wheel)"),
|
("zoom", "Zoom (drag; or wheel)"),
|
||||||
("fit", "Fit (F6)"),
|
("fit", "Fit (F6)"),
|
||||||
@@ -1921,6 +1941,7 @@ fn nav_bar(app: &mut SolveApp, ui: &mut egui::Ui, rect: Rect) {
|
|||||||
"zoom" => app.viewport.nav == Some(NavMode::Zoom),
|
"zoom" => app.viewport.nav == Some(NavMode::Zoom),
|
||||||
"perspective" => app.ui.perspective,
|
"perspective" => app.ui.perspective,
|
||||||
"settings" => app.ui.show_grid,
|
"settings" => app.ui.show_grid,
|
||||||
|
"spin" => app.viewport.spin,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if active || resp.hovered() {
|
if active || resp.hovered() {
|
||||||
@@ -1934,6 +1955,10 @@ fn nav_bar(app: &mut SolveApp, ui: &mut egui::Ui, rect: Rect) {
|
|||||||
"pan" => app.viewport.nav = toggle(NavMode::Pan, app.viewport.nav),
|
"pan" => app.viewport.nav = toggle(NavMode::Pan, app.viewport.nav),
|
||||||
"zoom" => app.viewport.nav = toggle(NavMode::Zoom, app.viewport.nav),
|
"zoom" => app.viewport.nav = toggle(NavMode::Zoom, app.viewport.nav),
|
||||||
"fit" => app.animate_view("fit"),
|
"fit" => app.animate_view("fit"),
|
||||||
|
"spin" => {
|
||||||
|
app.cancel_view_animation();
|
||||||
|
app.viewport.spin = !app.viewport.spin;
|
||||||
|
}
|
||||||
"home" => app.animate_view("home"),
|
"home" => app.animate_view("home"),
|
||||||
"lookat" => look_at_selection(app),
|
"lookat" => look_at_selection(app),
|
||||||
"style" => app.ui.visual_style = (app.ui.visual_style + 1) % 4,
|
"style" => app.ui.visual_style = (app.ui.visual_style + 1) % 4,
|
||||||
|
|||||||
Reference in new issue
Block a user