mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-12 21:32:52 +00:00
#3087: give a placeholder a match id that is one path segment
A pseudo effect's match name (Pseudo/0.25) was its group's match id, so a match path to its parameters (keyframe paste, pick whip) was cut apart at '/' and '.' and found nothing. The effect id stays the match name.
This commit is contained in:
3 files changed
+32
-8
No files matched your search
@@ -40,7 +40,9 @@ pub(crate) fn placeholder(
|
||||
refs: &mut Vec<PendingLayerRef>,
|
||||
col: &mut Collector,
|
||||
) -> PropGroup {
|
||||
let mut group = ids.group(fx.match_name(), shown);
|
||||
// The effect id is the match name; the group's match id is one segment of a property path
|
||||
// (a pseudo effect's `Pseudo/0.25` would be cut apart), so match paths find its parameters.
|
||||
let mut group = ids.group(&segment(fx.match_name()), shown);
|
||||
group.kind = GroupKind::Effect { effect: fx.match_name().to_string() };
|
||||
let here = format!("{}: '{}' effect '{shown}' ({})", cx.comp, cx.layer, fx.match_name());
|
||||
for p in params.iter().filter(|p| !carries_nothing(p)) {
|
||||
@@ -126,8 +128,18 @@ fn popup_len(p: &EffectParam<'_, '_>) -> Option<usize> {
|
||||
/// third-party effect's `CC Cylinder-0003`), else `param<index>` (a pseudo effect's
|
||||
/// `Pseudo/0.25-0001`: `/` and `.` separate path segments). Expressions also find it by its name.
|
||||
fn param_id(p: &EffectParam<'_, '_>) -> String {
|
||||
let plain = !p.match_name.is_empty() && p.match_name.chars().all(|c| c.is_alphanumeric() || matches!(c, ' ' | '-' | '_'));
|
||||
if plain { p.match_name.clone() } else { format!("param{}", p.index) }
|
||||
if !p.match_name.is_empty() && p.match_name.chars().all(plain) { p.match_name.clone() } else { format!("param{}", p.index) }
|
||||
}
|
||||
|
||||
/// Whether `c` can stand in one segment of a property path (`/`, `.`, `#` and `@` mean more).
|
||||
fn plain(c: char) -> bool {
|
||||
c.is_alphanumeric() || matches!(c, ' ' | '-' | '_')
|
||||
}
|
||||
|
||||
/// `name` as one segment of a property path: other characters become `_` (`Pseudo/0.25` is
|
||||
/// `Pseudo_0_25`).
|
||||
fn segment(name: &str) -> String {
|
||||
name.chars().map(|c| if plain(c) { c } else { '_' }).collect()
|
||||
}
|
||||
|
||||
/// Sets `prop` from `p`: its expression, then its keys or its value (the record, else the `pard`
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
use effectcraft_aep::import::{ImportOptions, ImportResult, LossCategory, import};
|
||||
use effectcraft_aep::{Body, Chunk, ParamKind, ParamValue, Project as AepProject, parse, write};
|
||||
use effectcraft_keyframe::Value;
|
||||
use effectcraft_project::{Project, PropGroup};
|
||||
use effectcraft_project::{GroupKind, Project, PropGroup};
|
||||
|
||||
const SYNTHETIC: &[u8] = include_bytes!("../../fixtures/synthetic.aep");
|
||||
|
||||
@@ -274,10 +274,15 @@ pub fn import_bytes(bytes: &[u8], effect: &str) -> (Option<PropGroup>, ImportRes
|
||||
let mut project = Project::default();
|
||||
let none = |_: &str| false;
|
||||
let r = import(&mut project, bytes, &ImportOptions { allow_losses: true, ..ImportOptions::new(&none) }).unwrap();
|
||||
let g = project
|
||||
.comps()
|
||||
.flat_map(|(_, c)| c.layers.iter())
|
||||
.find_map(|l| l.props.sub("effects").and_then(|fx| fx.children.iter().filter_map(|n| n.as_group()).find(|g| g.match_id == effect).cloned()));
|
||||
let g = project.comps().flat_map(|(_, c)| c.layers.iter()).find_map(|l| {
|
||||
l.props.sub("effects").and_then(|fx| {
|
||||
fx.children
|
||||
.iter()
|
||||
.filter_map(|n| n.as_group())
|
||||
.find(|g| g.match_id == effect || matches!(&g.kind, GroupKind::Effect { effect: e } if e == effect))
|
||||
.cloned()
|
||||
})
|
||||
});
|
||||
(g, r)
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,13 @@ fn a_pseudo_effect_is_kept_with_its_parameter_names() {
|
||||
assert_eq!(g.prop("param1").map(|p| (p.name.as_str(), p.value.clone())), Some(("Speed", Value::Scalar(4.0))));
|
||||
assert_eq!(g.prop("param2").map(|p| (p.name.as_str(), p.value.clone())), Some(("Mode", Value::Enum(1))));
|
||||
assert_eq!(losses(&r, LossCategory::Effects, "Pseudo/0.25").len(), 1);
|
||||
// The effect id stays the match name (Find Missing Effects, expressions); the group's match id
|
||||
// is one path segment, so a match path (keyframe paste, pick whip) finds its parameters again.
|
||||
assert_eq!(g.kind, GroupKind::Effect { effect: "Pseudo/0.25".into() });
|
||||
let speed = g.prop("param1").map(|p| p.uid);
|
||||
let layer = PropGroup::new(0, "layer", "Layer").with(PropGroup::new(0, "effects", "Effects").with(g));
|
||||
let path = speed.and_then(|u| layer.match_path_of(u));
|
||||
assert_eq!(path.as_deref().and_then(|p| layer.prop(p)).map(|p| p.name.as_str()), Some("Speed"), "{path:?}");
|
||||
}
|
||||
|
||||
/// A popup whose definition is borrowed (the project copy) and has no value record: its default
|
||||
|
||||
Reference in new issue
Block a user