mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 20:27:05 -06:00
Effects: Roughen and Pucker & Bloat show sliders (#4488)
This commit is contained in:
@@ -166,7 +166,8 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
||||
None if id == TEXTURIZER => glass_fields(app, ui, d, TEXTURIZER),
|
||||
None if id == TRANSFORM => transform_fields(ui, d, app.session.general_unit()),
|
||||
None if id == SCRIBBLE => scribble_fields(ui, d, app.session.general_unit()),
|
||||
None if id == ZIG_ZAG => zig_zag_fields(ui, d, app.session.general_unit()),
|
||||
None if id == ZIG_ZAG || id == ROUGHEN => size_fields(ui, d, &id, app.session.general_unit()),
|
||||
None if id == PUCKER_BLOAT => pucker_bloat_fields(ui, d),
|
||||
None if id == DROP_SHADOW => drop_shadow_fields(ui, d, app.session.general_unit()),
|
||||
None if id == "artistic.filmGrain" => film_grain_fields(ui, d),
|
||||
None if id == free_distort::FREE_DISTORT => {
|
||||
@@ -559,27 +560,40 @@ fn transform_fields(ui: &mut egui::Ui, d: &mut Dialog, unit: vectorcraft_doc::Un
|
||||
/// The Zig Zag effect (Effect › Distort & Transform › Zig Zag…).
|
||||
const ZIG_ZAG: &str = "distort.zigZag";
|
||||
|
||||
/// Zig Zag's dialog (#1133): Size and Ridges per segment as sliders with their fields, Relative or
|
||||
/// Absolute and the Points as radio buttons. Returns whether the values differ from those last
|
||||
/// previewed.
|
||||
fn zig_zag_fields(ui: &mut egui::Ui, d: &mut Dialog, unit: vectorcraft_doc::Unit) -> bool {
|
||||
/// The Roughen effect (Effect › Distort & Transform › Roughen…).
|
||||
const ROUGHEN: &str = "distort.roughen";
|
||||
|
||||
/// The Pucker & Bloat effect (Effect › Distort & Transform › Pucker & Bloat…).
|
||||
const PUCKER_BLOAT: &str = "distort.puckerBloat";
|
||||
|
||||
/// The second slider of [`size_fields`]: Zig Zag's Ridges per segment, Roughen's Detail (per inch),
|
||||
/// as (key, label, default, suffix).
|
||||
fn second_slider(effect: &str) -> (&'static str, &'static str, f64, &'static str) {
|
||||
if effect == ROUGHEN { ("detail", "Detail:", 10.0, "/in") } else { ("ridges", "Ridges per segment:", 4.0, "") }
|
||||
}
|
||||
|
||||
/// Zig Zag's and Roughen's dialog (#1133, #4488): Size and Ridges per segment (Roughen: Detail) as
|
||||
/// sliders with their fields, Relative or Absolute and the Points as radio buttons. Returns
|
||||
/// whether the values differ from those last previewed.
|
||||
fn size_fields(ui: &mut egui::Ui, d: &mut Dialog, effect: &str, unit: vectorcraft_doc::Unit) -> bool {
|
||||
const LABEL_W: f32 = 124.0;
|
||||
const FIELD_W: f32 = 70.0;
|
||||
let rail = Tokens::get(ui.ctx()).input_border;
|
||||
let track = move |_| rail;
|
||||
let relative = d.bool("relative");
|
||||
let size = if effect == ROUGHEN { 5.0 } else { 10.0 };
|
||||
widgets::subheader(ui, tl!("Options"));
|
||||
// Size is a share of the object's size (Relative) or a distance (Absolute).
|
||||
widgets::label_row(ui, tl!("Size:"), LABEL_W, |ui| {
|
||||
let shown = if relative {
|
||||
Some(widgets::SliderValue::field(d.f64("size", 10.0).clamp(0.0, 100.0), 0.0..=100.0, "%", 0))
|
||||
Some(widgets::SliderValue::field(d.f64("size", size).clamp(0.0, 100.0), 0.0..=100.0, "%", 0))
|
||||
} else {
|
||||
form::length_value(d, "size", unit, 0.0..=100.0)
|
||||
};
|
||||
form::slider_rail_valued(ui, d, "size", tl!("Size:"), 0.0..=100.0, shown, &track);
|
||||
if !relative {
|
||||
form::length(ui, d, "size", unit, FIELD_W);
|
||||
} else if let Some(n) = widgets::range_field(ui, ("zz", "size"), d.f64("size", 10.0), 0.0..=100.0, "%", 0, FIELD_W) {
|
||||
} else if let Some(n) = widgets::range_field(ui, ("zz", "size"), d.f64("size", size), 0.0..=100.0, "%", 0, FIELD_W) {
|
||||
d.fields.insert("size".into(), json!(n));
|
||||
}
|
||||
});
|
||||
@@ -591,17 +605,18 @@ fn zig_zag_fields(ui: &mut egui::Ui, d: &mut Dialog, unit: vectorcraft_doc::Unit
|
||||
}
|
||||
}
|
||||
});
|
||||
widgets::label_row(ui, tl!("Ridges per segment:"), LABEL_W, |ui| {
|
||||
form::slider_rail_named(ui, d, "ridges", tl!("Ridges per segment:"), 0.0..=100.0, &track);
|
||||
if let Some(n) = widgets::range_field(ui, ("zz", "ridges"), d.f64("ridges", 4.0), 0.0..=100.0, "", 0, FIELD_W) {
|
||||
d.fields.insert("ridges".into(), json!(n));
|
||||
let (key, label, default, suffix) = second_slider(effect);
|
||||
widgets::label_row(ui, tl!(label), LABEL_W, |ui| {
|
||||
form::slider_rail_named(ui, d, key, tl!(label), 0.0..=100.0, &track);
|
||||
if let Some(n) = widgets::range_field(ui, ("zz", key), d.f64(key, default), 0.0..=100.0, suffix, 0, FIELD_W) {
|
||||
d.fields.insert(key.into(), json!(n));
|
||||
}
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
widgets::subheader(ui, crate::i18n::tr_ctx(crate::i18n::current(), "effect", "Points"));
|
||||
let points = d.str("points");
|
||||
ui.horizontal(|ui| {
|
||||
for (label, value) in choices(ZIG_ZAG, "points").unwrap_or_default() {
|
||||
for (label, value) in choices(effect, "points").unwrap_or_default() {
|
||||
if widgets::radio(ui, crate::i18n::tr_ctx(crate::i18n::current(), "effect", label), points == *value, true) {
|
||||
d.fields.insert("points".into(), json!(value));
|
||||
}
|
||||
@@ -610,6 +625,15 @@ fn zig_zag_fields(ui: &mut egui::Ui, d: &mut Dialog, unit: vectorcraft_doc::Unit
|
||||
values_changed(d)
|
||||
}
|
||||
|
||||
/// Pucker & Bloat's dialog (#4488): its amount as a slider from Pucker (−200 %) to Bloat (200 %)
|
||||
/// with its field. Returns whether the value differs from the one last previewed.
|
||||
fn pucker_bloat_fields(ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
||||
let rail = Tokens::get(ui.ctx()).input_border;
|
||||
form::slider(ui, d, "amount", tl!("Amount:"), -200.0..=200.0, "%", &move |_| rail);
|
||||
form::slider_ends(ui, form::SLIDER_LABEL, (tl!("Pucker"), tl!("Bloat")));
|
||||
values_changed(d)
|
||||
}
|
||||
|
||||
/// Drop Shadow (Effect › Stylize › Drop Shadow…).
|
||||
const DROP_SHADOW: &str = "stylize.dropShadow";
|
||||
|
||||
|
||||
@@ -1413,6 +1413,35 @@ fn zig_zag_has_sliders_and_radio_buttons() {
|
||||
assert!(!lines.contains(&"Ridges:"), "{lines:?}");
|
||||
}
|
||||
|
||||
/// #4488: Roughen's dialog has Size and Detail sliders laid out as Zig Zag's, and Pucker & Bloat's
|
||||
/// its amount as a slider from Pucker to Bloat.
|
||||
#[test]
|
||||
fn roughen_and_pucker_bloat_have_sliders() {
|
||||
use crate::widgets::accessibility_tests::{slider_value, tree};
|
||||
let mut app = app();
|
||||
app.run("shape.rectangle", json!({"x": 10, "y": 10, "width": 50, "height": 50})).unwrap();
|
||||
app.run("effect.dialog", json!({"effect": "distort.roughen"})).unwrap();
|
||||
let text = crate::tests_labels::painted_text(&mut app, |app, ui| show(app, ui.ctx()));
|
||||
let lines: Vec<&str> = text.lines().map(str::trim).collect();
|
||||
for want in ["Size:", "Relative", "Absolute", "Detail:", "Points", "Smooth", "Corner"] {
|
||||
assert!(lines.contains(&want), "no {want:?} in {lines:?}");
|
||||
}
|
||||
let shown = tree(|ui| show(&mut app, ui.ctx()));
|
||||
assert_eq!(slider_value(&shown, "Size:"), (Some(5.0), Some(0.0), Some(100.0), Some("5%".into())));
|
||||
assert_eq!(slider_value(&shown, "Detail:"), (Some(10.0), Some(0.0), Some(100.0), None));
|
||||
app.ui.dialog = None;
|
||||
app.run("effect.dialog", json!({"effect": "distort.puckerBloat"})).unwrap();
|
||||
app.ui.dialog.as_mut().unwrap().fields.insert("amount".into(), json!(-60));
|
||||
let text = crate::tests_labels::painted_text(&mut app, |app, ui| show(app, ui.ctx()));
|
||||
let lines: Vec<&str> = text.lines().map(str::trim).collect();
|
||||
for want in ["Amount:", "Pucker", "Bloat"] {
|
||||
assert!(lines.contains(&want), "no {want:?} in {lines:?}");
|
||||
}
|
||||
let shown = tree(|ui| show(&mut app, ui.ctx()));
|
||||
let (value, min, max, _) = slider_value(&shown, "Amount:");
|
||||
assert_eq!((value, min, max), (Some(-60.0), Some(-200.0), Some(200.0)));
|
||||
}
|
||||
|
||||
/// Screen readers get the number and text of the field beside each dialog slider, in the field's
|
||||
/// unit, with the rail's range (extended to a number past the rail's end): Transform Each's Scale
|
||||
/// and Move, Zig Zag's Size and Ridges, a form slider (Vector Halftone's Frequency), the Pencil's
|
||||
|
||||
Reference in New Issue
Block a user