mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 10:09:32 -06:00
Text Range Selector: Start, End and Offset show as counts with Units = Index (#1814)
With Units set to Index the selector already counts characters (words,
lines), but the timeline kept showing Start, End and Offset as
percentages ("3.0%"), so switching looked like it did nothing. They are
now shown without the % sign while Units is Index
(render::text::in_index_units).
This commit is contained in:
@@ -187,6 +187,14 @@ pub fn range_value_of(f: f64, offset: f64, units_index: bool, n: usize) -> f64 {
|
||||
if units_index { (v * n as f64).round() } else { v * 100.0 }
|
||||
}
|
||||
|
||||
/// Whether property `uid` of `layer` is a Range Selector's Start, End or Offset while its Units
|
||||
/// are Index: the value is then a count of characters (words, lines), not a percentage.
|
||||
pub fn in_index_units(layer: &Layer, uid: effectcraft_project::Uid) -> bool {
|
||||
let Some(sel) = layer.props.parent_of(uid).filter(|g| g.match_id == "rangeSelector") else { return false };
|
||||
let is_range_value = sel.props().any(|p| p.uid == uid && matches!(p.match_id.as_str(), "start" | "end" | "offset"));
|
||||
is_range_value && sel.prop("advanced/units").is_some_and(|u| u.value == Value::Enum(1))
|
||||
}
|
||||
|
||||
/// Selection of every glyph by an animator's selectors, per dimension.
|
||||
pub fn animator_selection(ctx: &EvalCtx, layer: &Layer, anim: &PropGroup, lay: &TextLayout) -> Vec<[f64; 3]> {
|
||||
let sels: Vec<&PropGroup> = anim.sub("selectors").map(|s| s.groups().filter(|g| g.enabled).collect()).unwrap_or_default();
|
||||
|
||||
@@ -99,6 +99,24 @@ fn range_based_on_words_and_lines() {
|
||||
assert_eq!(s, vec![0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0], "{s:?}");
|
||||
}
|
||||
|
||||
/// With Units = Index a Range Selector's Start, End and Offset are character counts, not
|
||||
/// percentages (#1814); the selector's other values, and other selectors, are unaffected.
|
||||
#[test]
|
||||
fn index_units_mark_start_end_and_offset() {
|
||||
let (mut p, _cid, comp) = setup(400, 200);
|
||||
let mut l = text_layer(&mut p, &comp, doc("ABCDEFG", 30.0));
|
||||
animator(&mut p, &mut l, &["opacity"], &["range", "wiggly"]);
|
||||
let uid = |l: &Layer, path: &str| l.props.prop(path).unwrap_or_else(|| panic!("no {path}")).uid;
|
||||
let base = "text/animators/#1/selectors/#1";
|
||||
let range_values = ["start", "end", "offset"].map(|k| uid(&l, &format!("{base}/{k}")));
|
||||
assert!(range_values.iter().all(|u| !in_index_units(&l, *u)), "Percentage, the default");
|
||||
set(&mut l, &format!("{base}/advanced/units"), Value::Enum(1));
|
||||
assert!(range_values.iter().all(|u| in_index_units(&l, *u)));
|
||||
assert!(!in_index_units(&l, uid(&l, &format!("{base}/advanced/amount"))), "Amount stays a percentage");
|
||||
assert!(!in_index_units(&l, uid(&l, "text/animators/#1/properties/opacity")));
|
||||
assert!(!in_index_units(&l, uid(&l, "transform/opacity")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn range_start_end_and_offset_are_capped() {
|
||||
let (mut p, cid, comp) = setup(400, 200);
|
||||
|
||||
@@ -4117,7 +4117,9 @@ fn value_editor(
|
||||
set(actions, json!(nv));
|
||||
}
|
||||
} else {
|
||||
let suffix = if matches!(prop.ui, ParamUi::Percent) || prop.match_id == "opacity" { "%" } else { "" };
|
||||
// A Range Selector's Start, End and Offset count characters with Units = Index (#1814).
|
||||
let pct = (matches!(prop.ui, ParamUi::Percent) || prop.match_id == "opacity") && !effectcraft_engine::render::text::in_index_units(layer, uid);
|
||||
let suffix = if pct { "%" } else { "" };
|
||||
let (r, nv, _) = widgets::hot_number_at(ui, pos2(x, y), egui::Id::new(("v", uid, 0)), *v, speed, (min, max), dec.max(1), suffix, &t);
|
||||
app.auto.add(&format!("timeline.prop.{uid}.value"), r, &prop.name);
|
||||
if let Some(nv) = nv {
|
||||
|
||||
Reference in New Issue
Block a user