Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-pipeline/tests/camera_centred.rs

//! **The pipeline DAG opens centred, a click never moves it (📌 Stay), and 🎯 Focus
//! flies the clicked stage to the centre** — rendered: real egui frames, the pane
//! beside a 320 px rail (its canvas is NOT at the screen origin), real clicks.

use egui::{Pos2, Rect, Vec2};
use facett_core::fly::NavMode;
use facett_core::Facet;
use facett_pipeline::{PipelineView, Status};

fn view() -> PipelineView {
    let names = ["lint", "build", "test", "ui", "doctor"];
    PipelineView::new("runa", names.iter().map(|n| (n.to_string(), Status::Idle)).collect(), vec![(0, 1), (1, 2), (1, 3), (2, 4), (3, 4)])
}

struct Rig {
    ctx: egui::Context,
    t: f64,
    rail: f32,
}

impl Rig {
    fn new(mode: NavMode) -> Self {
        let ctx = egui::Context::default();
        ctx.set_pixels_per_point(1.0);
        mode.remember(&ctx);
        Self { ctx, t: 1.0, rail: 320.0 }
    }
    fn frame(&mut self, v: &mut PipelineView, events: Vec<egui::Event>) {
        self.t += 1.0 / 60.0;
        let input = egui::RawInput { screen_rect: Some(Rect::from_min_size(Pos2::ZERO, Vec2::new(1400.0, 900.0))), time: Some(self.t), events, ..Default::default() };
        let rail = self.rail;
        let mut out = self.ctx.run_ui(input, |ui| {
            egui::Panel::left("rail").exact_size(rail).resizable(false).show_inside(ui, |ui| {
                ui.label("rail");
            });
            egui::CentralPanel::default().show_inside(ui, |ui| v.ui(ui));
        });
        out.textures_delta.clear();
    }
    fn click(&mut self, v: &mut PipelineView, p: Pos2) {
        self.frame(v, vec![egui::Event::PointerMoved(p)]);
        let b = |pressed| egui::Event::PointerButton { pos: p, button: egui::PointerButton::Primary, pressed, modifiers: Default::default() };
        self.frame(v, vec![b(true)]);
        self.frame(v, vec![b(false)]);
    }
}

fn centre_of(v: &PipelineView, name: &str) -> Pos2 {
    let i = v.state().nodes.iter().position(|n| n.name == name).unwrap();
    v.nav().to_screen(v.layout_scene_centers()[i])
}

/// First load: fitted, CENTRED (±2 px) and wholly inside the visible canvas.
#[test]
fn the_dag_opens_centred_in_its_visible_canvas() {
    let mut rig = Rig::new(NavMode::Stay);
    let mut v = view();
    for _ in 0..4 {
        rig.frame(&mut v, Vec::new());
    }
    let (seen, b) = (v.seen_rect().expect("painted"), v.screen_box().expect("stages"));
    assert!((b.center() - seen.center()).length() <= 2.0, "centred: box {b:?} in {seen:?}");
    assert!(seen.expand(0.5).contains_rect(b), "fully visible: box {b:?} in {seen:?}");
    // the rail grows: the screen-space camera follows its canvas, the picture stays on it
    rig.rail = 480.0;
    for _ in 0..4 {
        rig.frame(&mut v, Vec::new());
    }
    let (seen, b) = (v.seen_rect().unwrap(), v.screen_box().unwrap());
    assert!(b.min.x >= seen.min.x - 0.5, "the picture moved with its canvas: box {b:?} in {seen:?}");
}

/// 📌 Stay: a click selects the stage and moves nothing.
#[test]
fn stay_a_click_never_moves_the_dag() {
    let mut rig = Rig::new(NavMode::Stay);
    let mut v = view();
    for _ in 0..4 {
        rig.frame(&mut v, Vec::new());
    }
    let p = centre_of(&v, "ui");
    let nav = *v.nav();
    rig.click(&mut v, p);
    for _ in 0..30 {
        rig.frame(&mut v, Vec::new());
    }
    assert_eq!(v.state().selected.as_deref(), Some("ui"));
    assert_eq!(*v.nav(), nav, "the camera did not move");
}

/// 🎯 Focus: the clicked stage flies to the centre of the visible canvas (±2 px).
#[test]
fn focus_a_click_flies_the_stage_to_the_centre() {
    let mut rig = Rig::new(NavMode::Focus);
    let mut v = view();
    for _ in 0..4 {
        rig.frame(&mut v, Vec::new());
    }
    let p = centre_of(&v, "doctor");
    rig.click(&mut v, p);
    for _ in 0..60 {
        rig.frame(&mut v, Vec::new());
    }
    let seen = v.seen_rect().unwrap();
    let at = centre_of(&v, "doctor");
    assert!((at - seen.center()).length() <= 2.0, "doctor at the centre: {at:?} vs {:?}", seen.center());
    assert!(v.nav().scale >= 1.0, "at a readable zoom: {}", v.nav().scale);
}