69 lines
3.3 KiB
Rust
69 lines
3.3 KiB
Rust
//! The Design panel's Arc fields drive the same `node.set` keys as the canvas handles: Start in
|
|
//! degrees, Sweep and Ratio as percentages, and number variables bound to them (sweep and ratio
|
|
//! variables hold percentages, like the fields).
|
|
|
|
use std::f64::consts::{PI, TAU};
|
|
|
|
use serde_json::{Value, json};
|
|
|
|
use crate::Session;
|
|
use crate::params::id_of;
|
|
use figcraft_doc::{NodeId, NodeKind};
|
|
|
|
fn ex(s: &mut Session, cmd: &str, p: Value) -> Value {
|
|
s.execute(cmd, &p).unwrap_or_else(|e| panic!("{cmd}: {e}"))
|
|
}
|
|
|
|
fn arc(s: &Session, id: NodeId) -> (f64, f64, f64) {
|
|
match s.doc().unwrap().node(id).unwrap().kind {
|
|
NodeKind::Ellipse { start, sweep, inner } => (start, sweep, inner),
|
|
_ => panic!("not an ellipse"),
|
|
}
|
|
}
|
|
|
|
fn ellipse(s: &mut Session) -> NodeId {
|
|
id_of(&ex(s, "shape.ellipse", json!({"x": 0, "y": 0, "width": 100, "height": 100}))["id"]).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn fields_write_degrees_and_percentages() {
|
|
let mut s = Session::new();
|
|
let e = ellipse(&mut s);
|
|
// What the fields send for Start 90°, Sweep 75% and Ratio 40%.
|
|
ex(&mut s, "node.set", json!({"id": e, "props": {"arcStart": 90, "arcSweep": 75.0 * 3.6, "arcInner": 0.4}}));
|
|
let (start, sweep, inner) = arc(&s, e);
|
|
assert!((start - PI / 2.0).abs() < 1e-9 && (sweep - 0.75 * TAU).abs() < 1e-9 && (inner - 0.4).abs() < 1e-9);
|
|
// A negative sweep runs the other way; past a full turn it holds at one.
|
|
ex(&mut s, "node.set", json!({"id": e, "props": {"arcSweep": -25.0 * 3.6}}));
|
|
assert!((arc(&s, e).1 + 0.25 * TAU).abs() < 1e-9);
|
|
ex(&mut s, "node.set", json!({"id": e, "props": {"arcSweep": 900}}));
|
|
assert!((arc(&s, e).1 - TAU).abs() < 1e-9);
|
|
// Inspect reports the arc the fields show.
|
|
ex(&mut s, "node.set", json!({"id": e, "props": {"arcSweep": 180}}));
|
|
let n = ex(&mut s, "node.get", json!({"id": e}));
|
|
assert!((n["arc"]["sweep"].as_f64().unwrap() - 180.0).abs() < 1e-9);
|
|
// Arc keys are for ellipses only.
|
|
let r = id_of(&ex(&mut s, "shape.rectangle", json!({"x": 0, "y": 0, "width": 10, "height": 10}))["id"]).unwrap();
|
|
assert!(s.execute("node.set", &json!({"id": r, "props": {"arcSweep": 90}})).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn variables_bound_to_the_arc_hold_what_the_fields_show() {
|
|
let mut s = Session::new();
|
|
let e = ellipse(&mut s);
|
|
ex(&mut s, "variable.createCollection", json!({"name": "Shape", "modes": ["A", "B"]}));
|
|
ex(&mut s, "variable.create", json!({"collection": "Shape", "name": "start", "type": "number", "value": 45}));
|
|
ex(&mut s, "variable.create", json!({"collection": "Shape", "name": "sweep", "type": "number", "value": 50}));
|
|
ex(&mut s, "variable.create", json!({"collection": "Shape", "name": "ratio", "type": "number", "value": 25}));
|
|
for (field, var) in [("arcStart", "start"), ("arcSweep", "sweep"), ("arcInner", "ratio")] {
|
|
ex(&mut s, "variable.bind", json!({"ids": [e], "field": field, "variable": var}));
|
|
}
|
|
let (start, sweep, inner) = arc(&s, e);
|
|
assert!((start - PI / 4.0).abs() < 1e-9, "degrees: {start}");
|
|
assert!((sweep - PI).abs() < 1e-9, "50% of a turn: {sweep}");
|
|
assert!((inner - 0.25).abs() < 1e-9, "25%: {inner}");
|
|
// A small ratio stays a percentage.
|
|
ex(&mut s, "variable.set", json!({"variable": "ratio", "value": 1}));
|
|
assert!((arc(&s, e).2 - 0.01).abs() < 1e-9, "{:?}", arc(&s, e));
|
|
}
|