vectorcraft/crates/ui-egui/src/dialogs/tests_perspective.rs

164 lines
7.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Perspective Grid dialogs: Define Grid, the presets manager and the tool options.
use serde_json::{Value, json};
use vectorcraft_engine::Session;
use vectorcraft_tools::distort::perspective::PerspectiveGrid;
use crate::{VectorcraftApp, theme};
fn frame(app: &mut VectorcraftApp) {
let ctx = egui::Context::default();
theme::install_fonts(&ctx);
let mut out = ctx.run_ui(egui::RawInput::default(), |ui| super::show(app, ui.ctx()));
out.textures_delta.clear();
}
fn app() -> VectorcraftApp {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.run("file.new", json!({"width": 800, "height": 600})).unwrap();
app
}
fn kind(app: &VectorcraftApp) -> Option<&str> {
app.ui.dialog.as_ref().map(|d| d.kind.as_str())
}
fn field(app: &VectorcraftApp, k: &str) -> Value {
app.ui.dialog.as_ref().and_then(|d| d.fields.get(k).cloned()).unwrap_or_default()
}
fn set(app: &mut VectorcraftApp, k: &str, v: Value) {
app.ui.dialog.as_mut().expect("a dialog is open").fields.insert(k.into(), v);
}
fn grid(app: &VectorcraftApp) -> PerspectiveGrid {
PerspectiveGrid::effective(&app.session.active().unwrap().doc)
}
#[test]
fn define_grid_opens_on_the_grid_and_applies_its_fields() {
let mut app = app();
app.run("perspective.grid.preset", json!({"kind": 3})).unwrap();
let g = grid(&app);
app.run("ui.perspectiveGridDialog", json!({})).unwrap();
assert_eq!(kind(&app), Some(super::perspective_grid::KIND));
assert_eq!(field(&app, "kind"), json!(3), "prefilled from the grid, not a fixed type");
assert!((field(&app, "gridline").as_f64().unwrap() - g.cell).abs() < 1e-9);
frame(&mut app);
// A new unit converts the lengths shown.
set(&mut app, "units", json!("inches"));
frame(&mut app);
assert!((field(&app, "gridline").as_f64().unwrap() - g.cell / 72.0).abs() < 1e-9);
// OK with nothing changed leaves the grid as it was.
super::confirm(&mut app).unwrap();
assert_eq!(kind(&app), None);
assert_eq!((grid(&app).cell, grid(&app).vp_left, grid(&app).kind), (g.cell, g.vp_left, 3));
// A new viewing angle and colour apply in one undo step.
let undo = app.session.active().unwrap().history.undo.len();
app.run("ui.perspectiveGridDialog", json!({})).unwrap();
set(&mut app, "angle", json!(30));
set(&mut app, "rightColor", json!("#112233"));
frame(&mut app);
super::confirm(&mut app).unwrap();
let n = grid(&app);
assert!((n.viewing_angle() - 30.0).abs() < 1e-9);
assert_eq!(n.right_color.hex(), "#112233");
assert_eq!(app.session.active().unwrap().history.undo.len(), undo + 1);
// A refused value keeps the dialog open.
app.run("ui.perspectiveGridDialog", json!({})).unwrap();
set(&mut app, "distance", json!(-5));
assert!(super::confirm(&mut app).is_err());
assert_eq!(kind(&app), Some(super::perspective_grid::KIND));
}
#[test]
fn define_grid_is_a_view_menu_item() {
let app = app();
let entries = crate::menus::menu_entries(&app);
let e = entries.iter().find(|e| e.command.as_deref() == Some("ui.perspectiveGridDialog")).expect("View › Perspective Grid › Define Grid…");
assert!(e.path.iter().any(|p| p == "Perspective Grid"), "{:?}", e.path);
assert!(e.enabled);
}
#[test]
fn define_grid_loads_and_saves_presets() {
let mut app = app();
app.run("ui.perspectiveGridDialog", json!({})).unwrap();
frame(&mut app);
assert_eq!(field(&app, "name"), json!("[2P-Normal View]"));
// Choosing a preset (an agent sets its fields; the menu loads them) keeps its name while the
// fields are its; a changed field makes the fields [Custom].
set(&mut app, "angle", json!(20));
frame(&mut app);
assert_eq!(field(&app, "name"), json!(""));
// Save Preset… asks for a name; OK saves the fields and comes back to Define Grid on it.
app.ui.dialog.as_mut().unwrap().fields.insert("__mode".into(), json!("save"));
set(&mut app, "__from", json!("define"));
set(&mut app, "name", json!("Shallow"));
frame(&mut app);
super::confirm(&mut app).unwrap();
assert_eq!(kind(&app), Some(super::perspective_grid::KIND));
assert_eq!((field(&app, "name"), field(&app, "__mode")), (json!("Shallow"), Value::Null));
assert_eq!(app.session.prefs.perspective_presets[0].angle, 20.0);
frame(&mut app);
assert_eq!(field(&app, "name"), json!("Shallow"), "the fields are the saved preset's");
super::confirm(&mut app).unwrap();
assert_eq!(grid(&app).name, "Shallow");
// View › Perspective Grid › Save Grid as Preset…: the grid under a new name.
app.run("ui.savePerspectivePreset", json!({})).unwrap();
assert_eq!(field(&app, "name"), json!("Perspective Preset 1"));
frame(&mut app);
super::confirm(&mut app).unwrap();
assert_eq!(kind(&app), None);
assert_eq!(app.session.prefs.perspective_presets.len(), 2);
}
#[test]
fn the_presets_manager_creates_edits_and_deletes_presets() {
use super::perspective_presets::{self, Action};
let mut app = app();
app.run("ui.perspectivePresetsDialog", json!({"selected": "[3P-Normal View]"})).unwrap();
frame(&mut app);
let press = |app: &mut VectorcraftApp, act: Action, current: &str| {
let mut d = app.ui.dialog.take().unwrap();
perspective_presets::run(app, &mut d, act, current).unwrap();
app.ui.dialog = Some(d);
frame(app);
};
// New… opens the editor on a copy of the selected preset; its OK comes back here.
press(&mut app, Action::New, "[3P-Normal View]");
assert_eq!((kind(&app), field(&app, "kind")), (Some(super::perspective_grid::KIND), json!(3)));
set(&mut app, "name", json!("Canyon"));
set(&mut app, "opacity", json!(90));
super::confirm(&mut app).unwrap();
assert_eq!((kind(&app), field(&app, "selected")), (Some(perspective_presets::KIND), json!("Canyon")));
// Edit… renames it.
press(&mut app, Action::Edit, "Canyon");
set(&mut app, "name", json!("Gorge"));
super::confirm(&mut app).unwrap();
assert_eq!(field(&app, "selected"), json!("Gorge"));
assert_eq!(app.session.prefs.perspective_presets.iter().map(|p| p.name.as_str()).collect::<Vec<_>>(), ["Gorge"]);
assert_eq!(app.session.prefs.perspective_presets[0].opacity, 90.0);
// Its type's menu lists it in a slot, which applies it.
assert_eq!(crate::menus::dynamic_label(&app, "ui.perspectiveUserPreset3.1", ""), "Gorge");
assert!(crate::menus::hidden_slot(&app, "ui.perspectiveUserPreset3.2") && crate::menus::hidden_slot(&app, "ui.perspectiveUserPreset2.1"));
app.run("ui.perspectiveUserPreset3.1", json!({})).unwrap();
assert_eq!(grid(&app).name, "Gorge");
// Delete selects the one above it.
press(&mut app, Action::Delete, "Gorge");
assert!(app.session.prefs.perspective_presets.is_empty());
assert_eq!(field(&app, "selected"), json!("[3P-Low View]"));
assert!(app.run("ui.perspectiveUserPreset3.1", json!({})).is_err());
}
#[test]
fn perspective_preset_menus_list_the_views_of_each_type() {
let app = app();
let entries = crate::menus::menu_entries(&app);
let under = |sub: &str| entries.iter().filter(|e| e.path.iter().any(|p| p == sub)).map(|e| e.label.clone()).collect::<Vec<_>>();
assert_eq!(under("One Point Perspective"), ["[1P-Normal View]", "[1P-Low View]", "[1P-High View]"]);
assert_eq!(under("Three Point Perspective"), ["[3P-Normal View]", "[3P-Low View]"]);
let presets = entries.iter().find(|e| e.command.as_deref() == Some("ui.perspectivePresetsDialog")).unwrap();
assert_eq!((presets.label.as_str(), presets.path.first().map(String::as_str)), ("Perspective Grid Presets…", Some("Edit")));
}