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
@@ -233,7 +233,8 @@ export function easedShare(
|
||||
): number {
|
||||
const { shape, direction, curve } = easingOf(interpolation);
|
||||
if (shape === 'linear') return t;
|
||||
if (shape === 'step') return 0;
|
||||
// A key reads the next key's own value once it is there, so for it a step only ever holds.
|
||||
if (shape === 'step') return t >= 1 ? 1 : 0;
|
||||
if (shape === 'curve') {
|
||||
const points = curves(curve ?? '');
|
||||
return points ? curveValue(points, t) : t;
|
||||
@@ -249,6 +250,19 @@ export function easedShare(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An easing as something that runs on its own clock, the audio one: the two shapes it has built in
|
||||
* stay names, everything else is the share at each `t`, a gone curve already read as linear.
|
||||
*/
|
||||
export type EaseShare = 'linear' | 'step' | ((t: number) => number);
|
||||
|
||||
export function easeShareOf(interpolation: KeyInterpolation, curves: CurveLookup = NO_CURVES): EaseShare {
|
||||
const { shape, curve } = easingOf(interpolation);
|
||||
if (shape === 'linear' || shape === 'step') return shape;
|
||||
if (shape === 'curve' && !curves(curve ?? '')) return 'linear';
|
||||
return (t) => easedShare(interpolation, t, curves);
|
||||
}
|
||||
|
||||
/** The value between two keys, `t` from 0 (at `a`) to 1 (at `b`). */
|
||||
export function blendValue(kind: string, a: PropertyValue, b: PropertyValue, t: number): PropertyValue {
|
||||
if (kind === 'number') {
|
||||
|
||||
@@ -15,8 +15,10 @@ import { cloneVectorPoint } from './vectorart';
|
||||
/** The node type that eases along a curve, and its setting naming the curve. */
|
||||
export const LERP = 'Lerp';
|
||||
export const LERP_CURVE = 'curve';
|
||||
/** Every node type with the easing settings of a `Lerp`, the curve among them. */
|
||||
export const EASED_NODES: readonly string[] = [LERP, 'SetSoundFxParameters'];
|
||||
|
||||
/** How many animation keys and `Lerp` nodes ease along a curve – what deleting it has to warn about. */
|
||||
/** How many animation keys and eased nodes run along a curve – what deleting it has to warn about. */
|
||||
export function curveUsages(project: Project, curveId: string): { keys: number; nodes: number } {
|
||||
let keys = 0;
|
||||
let nodes = 0;
|
||||
@@ -25,7 +27,9 @@ export function curveUsages(project: Project, curveId: string): { keys: number;
|
||||
for (const track of asset.tracks)
|
||||
keys += track.keys.filter((key) => key.interpolation === `curve:${curveId}`).length;
|
||||
if (isGraphAsset(asset))
|
||||
nodes += asset.graph.nodes.filter((n) => n.type === LERP && n.params[LERP_CURVE] === curveId).length;
|
||||
nodes += asset.graph.nodes.filter(
|
||||
(n) => EASED_NODES.includes(n.type) && n.params[LERP_CURVE] === curveId,
|
||||
).length;
|
||||
}
|
||||
return { keys, nodes };
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user