mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 21:16:52 -06:00
Merge pull request #289 from storytold/fix/227-shape-effect-points
Effects: effect points on shape layers start at the layer centre (#227) # Conflicts: # crates/ui-egui/src/panels/puppet_tool.rs # crates/ui-egui/src/panels/viewer.rs
This commit is contained in:
@@ -253,8 +253,6 @@ pub(crate) fn chain_key(chain: &[FxStep], buf: &Buf, levels: Option<f32>) -> u12
|
||||
k.debug(&e.working_space);
|
||||
k.u64(e.working_linear as u64);
|
||||
k.debug(&e.shutter);
|
||||
k.f64(e.bounds_origin[0]);
|
||||
k.f64(e.bounds_origin[1]);
|
||||
}
|
||||
k.finish()
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ fn bulge(e: &mut Enc, ctx: &EffectCtx, b: GBuf) -> Option<GBuf> {
|
||||
let h = ctx.params.f("height");
|
||||
let taper = 1.0 + ctx.params.f("taperRadius").max(0.0) / 100.0 * 3.0;
|
||||
let pin = ctx.params.b("pinAllEdges");
|
||||
let (x0, y0, lw, lh) = util::pin_rect(ctx, b.offset, b.scale);
|
||||
let (x0, y0, lw, lh) = util::layer_rect_at(ctx, b.offset, b.scale);
|
||||
let edge = (lw.min(lh) * 0.1).max(1.0);
|
||||
let mut p = Params::default();
|
||||
p.f[0] = [c.0 as f32, c.1 as f32, rx as f32, ry as f32];
|
||||
@@ -115,7 +115,7 @@ fn wave_warp(e: &mut Enc, ctx: &EffectCtx, mut b: GBuf) -> Option<GBuf> {
|
||||
if !ctx.adjustment {
|
||||
b.pad(e, h.abs().ceil() as u32 + 1)?;
|
||||
}
|
||||
let (x0, y0, lw, lh) = util::pin_rect(ctx, b.offset, b.scale);
|
||||
let (x0, y0, lw, lh) = util::layer_rect_at(ctx, b.offset, b.scale);
|
||||
let rect = [x0 as f32, y0 as f32, lw.max(1.0) as f32, lh.max(1.0) as f32];
|
||||
// The wave phase in cycles, (x·dx + y·dy) / width + phase / 2π, is separable: per column
|
||||
// and per row (fraction, whole cycles) in f64, so the kernel's sum keeps the fraction exact
|
||||
@@ -183,7 +183,7 @@ fn turbulent(e: &mut Enc, ctx: &EffectCtx, mut b: GBuf) -> Option<GBuf> {
|
||||
let evo = ctx.params.f("evolution") / 360.0;
|
||||
let cycle = ctx.params.b("evolutionOptions/cycleEvolution").then(|| ctx.params.f("evolutionOptions/cycle").round().max(1.0));
|
||||
let falloff = if (3..=5).contains(&kind) { 0.3 } else { 0.5 };
|
||||
let (x0, y0, lw, lh) = util::pin_rect(ctx, b.offset, b.scale);
|
||||
let (x0, y0, lw, lh) = util::layer_rect_at(ctx, b.offset, b.scale);
|
||||
let edge = (lw.min(lh) * 0.1).max(1.0);
|
||||
let seed = (ctx.seed ^ 0x7d15).wrapping_add((ctx.params.f("evolutionOptions/randomSeed") as i64 as u32).wrapping_mul(0x9e37_79b9));
|
||||
let (z0, z1, t) = match cycle {
|
||||
|
||||
@@ -125,7 +125,7 @@ fn run(e: &mut Enc, entry: &str, p: &Params, mut b: GBuf, data: Option<&wgpu::Bu
|
||||
|
||||
/// util::layer_rect.
|
||||
fn layer_rect(ctx: &EffectCtx, b: &GBuf) -> (f64, f64, f64, f64) {
|
||||
(b.offset[0], b.offset[1], ctx.layer_size[0] * b.scale, ctx.layer_size[1] * b.scale)
|
||||
effectcraft_effects::util::layer_rect_at(ctx, b.offset, b.scale)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- per-pixel (fxs_point)
|
||||
|
||||
@@ -160,8 +160,8 @@ impl Scene {
|
||||
pub(crate) fn effect(&mut self, l: &mut Layer, id: &str, vals: &[(&str, Value)]) {
|
||||
let spec = effectcraft_effects::find(id).unwrap();
|
||||
let mut next = self.p.next_id;
|
||||
let size = effectcraft_render::source_size(&self.p, l);
|
||||
let mut g = effectcraft_effects::instantiate(spec, &mut Ids(&mut next), spec.name, [size.0 as f64, size.1 as f64]);
|
||||
let size = effectcraft_render::effect_bounds(&self.p, &self.comp, l).0;
|
||||
let mut g = effectcraft_effects::instantiate(spec, &mut Ids(&mut next), spec.name, size);
|
||||
self.p.next_id = next;
|
||||
for (k, v) in vals {
|
||||
g.prop_mut(k).unwrap_or_else(|| panic!("{id}: no {k}")).value = v.clone();
|
||||
|
||||
@@ -55,28 +55,44 @@ fn turbulent_displace_and_cc_lens() {
|
||||
effect_case("ec.distort.cclens", &[("convergence", n(-70.0))]);
|
||||
}
|
||||
|
||||
/// Edge pinning on a shape layer, whose comp-sized bounds are centred on its origin (#227).
|
||||
/// Effect `id` on a shape layer, whose comp-sized bounds are centred on its origin and whose
|
||||
/// effects run in effect space from the bounds' top-left (#227), at full and half resolution
|
||||
/// (the 97 × 61 comp puts that corner between pixels).
|
||||
fn shape_case(id: &str, vals: &[(&str, Value)]) {
|
||||
let mut s = Scene::new(BitDepth::Bpc32);
|
||||
let mut l = build::layer(&mut s.p, &s.comp, "Shape", LayerSource::Shape, (97, 61), None);
|
||||
let mut next = s.p.next_id;
|
||||
let mut ids = Ids(&mut next);
|
||||
let rect = build::shape_rect(&mut ids, [90.0, 54.0], [0.0, 0.0], 0.0);
|
||||
let fill = build::shape_fill(&mut ids, [0.9, 0.3, 0.1, 1.0]);
|
||||
let g = build::shape_group(&mut ids, "Rectangle 1", vec![rect, fill]);
|
||||
s.p.next_id = next;
|
||||
l.props.sub_mut("contents").unwrap().children.push(g.into());
|
||||
s.effect(&mut l, id, vals);
|
||||
s.push(l);
|
||||
check(&format!("{id} on a shape layer"), compare_at(&s, opts(), Tick::ZERO), 0.0);
|
||||
check(&format!("{id} on a shape layer, half"), compare_at(&s, RenderOpts { scale: 0.5, ..opts() }, Tick::ZERO), 0.0);
|
||||
}
|
||||
|
||||
/// Edge pinning on a shape layer (#227).
|
||||
#[test]
|
||||
fn edge_pinning_on_a_shape_layer() {
|
||||
let cases: [(&str, &[(&str, Value)]); 3] = [
|
||||
("ec.distort.turbulentdisplace", &[("size", n(30.0)), ("amount", n(20.0))]),
|
||||
("ec.distort.wavewarp", &[("pinning", e(1)), ("height", n(6.0)), ("width", n(25.0))]),
|
||||
("ec.distort.bulge", &[("pinAllEdges", on()), ("height", n(2.0)), ("hradius", n(40.0)), ("vradius", n(30.0)), ("center", Value::Vec2([-20.0, -10.0]))]),
|
||||
];
|
||||
for (id, vals) in cases {
|
||||
let mut s = Scene::new(BitDepth::Bpc32);
|
||||
let mut l = build::layer(&mut s.p, &s.comp, "Shape", LayerSource::Shape, (97, 61), None);
|
||||
let mut next = s.p.next_id;
|
||||
let mut ids = Ids(&mut next);
|
||||
let rect = build::shape_rect(&mut ids, [90.0, 54.0], [0.0, 0.0], 0.0);
|
||||
let fill = build::shape_fill(&mut ids, [0.9, 0.3, 0.1, 1.0]);
|
||||
let g = build::shape_group(&mut ids, "Rectangle 1", vec![rect, fill]);
|
||||
s.p.next_id = next;
|
||||
l.props.sub_mut("contents").unwrap().children.push(g.into());
|
||||
s.effect(&mut l, id, vals);
|
||||
s.push(l);
|
||||
check(&format!("{id} on a shape layer"), compare_at(&s, opts(), Tick::ZERO), 0.0);
|
||||
}
|
||||
shape_case("ec.distort.turbulentdisplace", &[("size", n(30.0)), ("amount", n(20.0))]);
|
||||
shape_case("ec.distort.wavewarp", &[("pinning", e(1)), ("height", n(6.0)), ("width", n(25.0))]);
|
||||
shape_case(
|
||||
"ec.distort.bulge",
|
||||
&[("pinAllEdges", on()), ("height", n(2.0)), ("hradius", n(40.0)), ("vradius", n(30.0)), ("center", Value::Vec2([28.5, 20.5]))],
|
||||
);
|
||||
}
|
||||
|
||||
/// Effect points on a shape layer at their defaults (the bounds' centre) and set (#227).
|
||||
#[test]
|
||||
fn effect_points_on_a_shape_layer() {
|
||||
shape_case("ec.distort.twirl", &[("angle", n(120.0))]);
|
||||
shape_case("ec.distort.bulge", &[("hradius", n(30.0)), ("vradius", n(20.0)), ("height", n(1.8))]);
|
||||
shape_case("ec.distort.ripple", &[("radius", n(80.0)), ("waveWidth", n(9.0)), ("waveHeight", n(4.0))]);
|
||||
shape_case("ec.distort.cclens", &[("size", n(45.0)), ("convergence", n(60.0)), ("center", Value::Vec2([30.0, 20.0]))]);
|
||||
shape_case("ec.distort.turbulentdisplace", &[("size", n(25.0)), ("amount", n(30.0)), ("offset", Value::Vec2([10.0, 40.0]))]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user