Offer the easings of an animation key on Lerp and sound FX ramps
A timed Set sound FX parameters ran only linearly, and a Lerp had four quadratic eases of its own. An animation key already had the full set. Now all three offer the same choice: Linear, Step, the ten curves from Sine to Bounce with In, Out or In-out, and a drawn Curve asset. - easingParams in src/core/graph/nodes/easing.ts gives a node the fields Easing, Direction and Curve from the key's own lists, and easingOfParams reads them back as a key interpolation. - There is no migration. A Lerp saved with the old in, out or inOut runs linear until its easing is picked again. - Set sound FX parameters hands the easing to the player. Linear and Step stay ramps of the audio clock, every other easing goes to setValueCurveAtTime as 200 samples a second, in semitones and dB. - Step now reaches its end at t 1. A key never asked for that, it reads the next key itself, so animations play as before. - The curve-in-use count and the warning for a gone curve cover the sound node too. Tests: - node-catalog: Lerp with cubic in, quad out and in-out, a curve without a direction, step, an unknown easing as linear. The sound node hands on a curve, step and a gone curve as linear. - sound-library: an eased change becomes a curve in semitones and decibels, a step a jump at the end. - node-catalog and curve after dropping the old values: 399, green. - e2e 6, 34, 53 on melektaus-atx: ALL PASSED, 198 checks. In Chrome a 2 s Quad in from depth 7 to -5 read speed 0.864 early and 0.5 at the end, a 1 s Step held 1 and then jumped to 0.5. - Counter-check: with curves sent as linear ramps, the curve test of the sound library fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
501a1524ed
commit
e7a360db73
17 files changed
+347
-104
No files matched your search
@@ -834,25 +834,65 @@ const CASES: Record<string, Case[]> = {
|
||||
],
|
||||
Lerp: [
|
||||
{ name: 'linear by default', inputs: { a: 10, b: 20, t: 0.25 }, outputs: { result: 12.5 } },
|
||||
{ name: 'ease in', inputs: { a: 0, b: 8, t: 0.5 }, params: { ease: 'in' }, outputs: { result: 2 } },
|
||||
{ name: 'ease out', inputs: { a: 0, b: 8, t: 0.5 }, params: { ease: 'out' }, outputs: { result: 6 } },
|
||||
{
|
||||
name: 'ease in-out, slow at both ends',
|
||||
inputs: { a: 0, b: 8, t: 0.25 },
|
||||
params: { ease: 'inOut' },
|
||||
name: 'the easings of an animation key: cubic in',
|
||||
inputs: { a: 0, b: 8, t: 0.5 },
|
||||
params: { ease: 'cubic', direction: 'in' },
|
||||
outputs: { result: 1 },
|
||||
},
|
||||
{
|
||||
name: 'ease in-out, half way at the middle',
|
||||
name: 'quad out',
|
||||
inputs: { a: 0, b: 8, t: 0.5 },
|
||||
params: { ease: 'inOut' },
|
||||
params: { ease: 'quad', direction: 'out' },
|
||||
outputs: { result: 6 },
|
||||
},
|
||||
{
|
||||
name: 'a curve without a direction set eases both ways',
|
||||
inputs: { a: 0, b: 8, t: 0.25 },
|
||||
params: { ease: 'cubic' },
|
||||
outputs: { result: 0.5 },
|
||||
},
|
||||
{
|
||||
name: 'step stays at a until t reaches 1',
|
||||
inputs: { a: 2, b: 8, t: 0.99 },
|
||||
params: { ease: 'step' },
|
||||
outputs: { result: 2 },
|
||||
},
|
||||
{
|
||||
name: 'step at t 1 is b',
|
||||
inputs: { a: 2, b: 8, t: 1 },
|
||||
params: { ease: 'step' },
|
||||
outputs: { result: 8 },
|
||||
},
|
||||
{
|
||||
name: 'a direction says nothing for linear',
|
||||
inputs: { a: 0, b: 8, t: 0.5 },
|
||||
params: { ease: 'linear', direction: 'in' },
|
||||
outputs: { result: 4 },
|
||||
},
|
||||
{
|
||||
name: 'quad in-out, slow at both ends',
|
||||
inputs: { a: 0, b: 8, t: 0.25 },
|
||||
params: { ease: 'quad', direction: 'in-out' },
|
||||
outputs: { result: 1 },
|
||||
},
|
||||
{
|
||||
name: 'quad in-out, half way at the middle',
|
||||
inputs: { a: 0, b: 8, t: 0.5 },
|
||||
params: { ease: 'quad', direction: 'in-out' },
|
||||
outputs: { result: 4 },
|
||||
},
|
||||
{
|
||||
name: 'an unknown easing runs linear',
|
||||
inputs: { a: 0, b: 8, t: 0.25 },
|
||||
params: { ease: 'in' },
|
||||
outputs: { result: 2 },
|
||||
},
|
||||
{ name: 't past 1 stops at b', inputs: { a: 3, b: -5, t: 1.2 }, outputs: { result: -5 } },
|
||||
{
|
||||
name: 't below 0 stops at a',
|
||||
inputs: { a: 3, b: -5, t: -0.5 },
|
||||
params: { ease: 'out' },
|
||||
params: { ease: 'quad', direction: 'out' },
|
||||
outputs: { result: 3 },
|
||||
},
|
||||
{
|
||||
@@ -2032,19 +2072,58 @@ const CASES: Record<string, Case[]> = {
|
||||
name: 'hands the numbers of the bundle to the voice it is given',
|
||||
inputs: { voice: 4, fxParams: { depth: 3, label: 'x' } },
|
||||
next: 'exec',
|
||||
after: (ctx) => expect(ctx.tuned).toEqual([{ voice: 4, fxParams: { depth: 3 }, time: 0 }]),
|
||||
after: (ctx) =>
|
||||
expect(ctx.tuned).toEqual([{ voice: 4, fxParams: { depth: 3 }, time: 0, ease: 'linear' }]),
|
||||
},
|
||||
{
|
||||
name: 'hands on the time the values take to get there',
|
||||
inputs: { voice: 4, fxParams: { depth: -64 }, time: 1.28 },
|
||||
next: 'exec',
|
||||
after: (ctx) => expect(ctx.tuned).toEqual([{ voice: 4, fxParams: { depth: -64 }, time: 1.28 }]),
|
||||
after: (ctx) =>
|
||||
expect(ctx.tuned).toEqual([{ voice: 4, fxParams: { depth: -64 }, time: 1.28, ease: 'linear' }]),
|
||||
},
|
||||
{
|
||||
name: 'a time below 0 is a quick glide',
|
||||
inputs: { voice: 4, fxParams: { depth: 3 }, time: -2 },
|
||||
next: 'exec',
|
||||
after: (ctx) => expect(ctx.tuned).toEqual([{ voice: 4, fxParams: { depth: 3 }, time: 0 }]),
|
||||
after: (ctx) =>
|
||||
expect(ctx.tuned).toEqual([{ voice: 4, fxParams: { depth: 3 }, time: 0, ease: 'linear' }]),
|
||||
},
|
||||
{
|
||||
name: 'hands on the easing the values take: a curve with its direction as a share of the way',
|
||||
inputs: { voice: 4, fxParams: { depth: 3 }, time: 1 },
|
||||
params: { ease: 'cubic', direction: 'in' },
|
||||
next: 'exec',
|
||||
after: (ctx) => {
|
||||
const ease = ctx.tuned[0]!.ease;
|
||||
expect(typeof ease === 'function' && [ease(0), ease(0.5), ease(1)]).toEqual([0, 0.125, 1]);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'step is handed on by name, the clock jumps at the end',
|
||||
inputs: { voice: 4, fxParams: { depth: 3 }, time: 1 },
|
||||
params: { ease: 'step' },
|
||||
next: 'exec',
|
||||
after: (ctx) => expect(ctx.tuned[0]!.ease).toBe('step'),
|
||||
},
|
||||
{
|
||||
name: 'along a Curve asset, as a share that may overshoot',
|
||||
inputs: { voice: 4, fxParams: { depth: 3 }, time: 1 },
|
||||
params: { ease: 'curve', curve: 'c' },
|
||||
lookup: overshootingCurve,
|
||||
next: 'exec',
|
||||
after: (ctx) => {
|
||||
const ease = ctx.tuned[0]!.ease;
|
||||
expect(typeof ease === 'function' && ease(0.5)).toBeCloseTo(1.5, 6);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'a Curve asset that is gone is linear',
|
||||
inputs: { voice: 4, fxParams: { depth: 3 }, time: 1 },
|
||||
params: { ease: 'curve', curve: 'gone' },
|
||||
lookup: overshootingCurve,
|
||||
next: 'exec',
|
||||
after: (ctx) => expect(ctx.tuned[0]!.ease).toBe('linear'),
|
||||
},
|
||||
{
|
||||
name: 'voice 0 – nothing was played – reaches nothing, and the flow carries on',
|
||||
|
||||
Reference in new issue
Block a user