Skip to main content

drew_sim/
camera.rs

1//! Caméra orbitale et gestion de l'entrée utilisateur (zoom, pan, orbite).
2
3use eframe::egui;
4
5/// Bornes de zoom par défaut.
6pub const DEFAULT_ZOOM_RANGE: (f32, f32) = (0.2, 5.0);
7
8/// État de la caméra orbitale : angle d'orbite, zoom, décalage de panoramique.
9#[derive(Clone, Copy, Debug)]
10pub struct OrbitCamera {
11    pub orbit: f32,
12    pub zoom: f32,
13    pub pan_offset: egui::Vec2,
14    pub zoom_range: (f32, f32),
15}
16
17impl Default for OrbitCamera {
18    fn default() -> Self {
19        Self {
20            orbit: 0.5,
21            zoom: 1.0,
22            pan_offset: egui::Vec2::ZERO,
23            zoom_range: DEFAULT_ZOOM_RANGE,
24        }
25    }
26}
27
28impl OrbitCamera {
29    /// Met à jour la caméra à partir de la réponse d'interaction egui pour
30    /// la zone de rendu (molette = zoom, clic droit/milieu + glisser = pan,
31    /// clic gauche + glisser = orbite).
32    pub fn handle_input(&mut self, ui: &egui::Ui, response: &egui::Response) {
33        if response.hovered() {
34            let scroll_delta = ui.input(|i| i.smooth_scroll_delta.y);
35            if scroll_delta != 0.0 {
36                self.zoom = (self.zoom + scroll_delta * 0.002)
37                    .clamp(self.zoom_range.0, self.zoom_range.1);
38            }
39        }
40
41        if response.dragged() {
42            let delta = response.drag_delta();
43            let panning = ui.input(|i| {
44                i.pointer.button_down(egui::PointerButton::Secondary)
45                    || i.pointer.button_down(egui::PointerButton::Middle)
46            });
47            if panning {
48                self.pan_offset += delta;
49            } else {
50                self.orbit += delta.x * 0.01;
51            }
52        }
53    }
54}