mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 13:08:07 -06:00
Effects: a host evaluates one effect parameter at another layer time (#1373)
EffectHost::param_at(effect_index, id, layer_time) evaluates a single parameter (by its flattened id, such as birthRate or group/param) of the effect at that index in the layer's stack. A simulation can then sample one parameter at every step without flattening the whole effect each time. The effect index is passed in, rather than read from the renderer's running-effect index as params_at does: GPU-batched effects never update that index, so a batched effect would read another effect's parameters. The renderer's implementation walks the effect group by match id and evaluates just that property (keyframes and expressions) at the comp time of the layer time.
This commit is contained in:
@@ -383,6 +383,13 @@ pub trait EffectHost: Sync {
|
||||
fn params_at(&self, _layer_time: f64) -> Option<Params> {
|
||||
None
|
||||
}
|
||||
/// Parameter `id` (a [`flatten_params`] id such as `birthRate`) of effect `effect_index` in
|
||||
/// the layer's stack (the running effect's [`EffectEnv::effect_index`]) at another **layer
|
||||
/// time**: CC Particle World samples its Birth Rate at every step it simulates (#1373).
|
||||
/// `None` when unavailable.
|
||||
fn param_at(&self, _effect_index: usize, _id: &str, _layer_time: f64) -> Option<Value> {
|
||||
None
|
||||
}
|
||||
/// A particle simulation backend (GPU particles; see [`psim`]). `None` = simulate on the
|
||||
/// CPU.
|
||||
fn particles(&self) -> Option<&dyn psim::ParticleSim> {
|
||||
|
||||
@@ -343,6 +343,27 @@ impl EffectHost for FxHost<'_, '_, '_> {
|
||||
Some(effectcraft_effects::flatten_params(g, &mut |pr| ctx.value(self.layer, pr)))
|
||||
}
|
||||
|
||||
fn param_at(&self, effect_index: usize, id: &str, layer_time: f64) -> Option<effectcraft_keyframe::Value> {
|
||||
// Only the one property: a simulation samples it at every step.
|
||||
let mut g = self.layer.effects()?.groups().nth(effect_index)?;
|
||||
let mut path = id.split('/').peekable();
|
||||
while let Some(m) = path.next() {
|
||||
if path.peek().is_none() {
|
||||
let p = g.children.iter().find_map(|c| match c {
|
||||
effectcraft_project::Node::Prop(p) if p.match_id == m => Some(p),
|
||||
_ => None,
|
||||
})?;
|
||||
let ctx = self.ctx.at(self.layer.comp_time(Tick::from_seconds_f64(layer_time)));
|
||||
return Some(ctx.value(self.layer, p));
|
||||
}
|
||||
g = g.children.iter().find_map(|c| match c {
|
||||
effectcraft_project::Node::Group(sg) if sg.match_id == m => Some(sg),
|
||||
_ => None,
|
||||
})?;
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn comp_scene(&self) -> Option<effectcraft_effects::CompScene> {
|
||||
Some(comp_scene(self.ctx, self.layer)?.rebased(self.origin))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user