Skip to content

v0.17.0

Choose a tag to compare

@rawframe-release rawframe-release released this 03 Nov 10:23
4364725

0.17.0 (2026-11-03)

This release changes two results to follow the references they name, ahead of 1.0.0. A finished player given a new rate runs at it from the time it holds, so a positive rate keeps it finished at its end where it jumped back (#264). A path's direction through a hold or a step is the way the path goes on, as SVG 2's path directionality takes it, where it was the way it came (#266). The clips guide's GSAP porting notes now cover grids with fewer items than columns and every way a clip's positions differ from GSAP's timeline, each checked against GSAP 3.15.0's outputs (#260, #262). Results change for a finished player given a positive rate (its time, the values it writes and its records), and for the direction and angle a host asks of a timed path through a hold or a step.

Changed

  • Breaking: mtwnClipPlayer_SetRate on a finished player runs it at the new rate from the time it holds, its start time set again from it, start = now - current / rate (#264). A positive rate keeps the player finished there. It kept the start time it finished with, as Web Animations' setting of the playback rate leaves it, so the next update put it back at (now - start) * rate: a 2 s clip finished at 12 s and given 0.5 at 12.5 s jumped back to 1.3 s and finished again at 14 s.
    • A finish after the change is no longer taken back, and the event records change with it: no iteration or end is crossed again.
    • A negative rate plays the player back from there at once, as before. Every other state takes the rate as before, by Web Animations' seamless update of the playback rate.
    • The specification's own seamless procedure would instead keep a finished player at its end for as long as it stood finished before a negative rate moves it. docs/internals/timing.md names this, and a running player's pending rate, as the two places the players depart from the specification's text.
    • tools/oracle/player_oracle.py writes Level 1's player procedures again from the specification, with those two departures, and test_player matches its 300 scripts to the bit.
  • Breaking: mtwnComputePathDirection and mtwnComputePathAngle give a timed hold (a segment of no length between keyframes at different offsets) and a step the direction of the nearest later segment with a length, at its start, as SVG 2 moves past a segment of no length (#266). They gave the nearest earlier one, at its end. A path right to (1, 0), held there from 0.4 to 0.6 and then up, faced along x through the hold, and now faces up from 0.4.
    • Only at the path's end, where no segment with a length follows, do they still take the earlier one. A plain corner, a path without holds or steps, and every path at constant speed give the same bits.
    • The header and the values guide say that a cusp's outgoing direction is the library's choice, since SVG 2 leaves it open, and that Chrome takes the incoming direction at every boundary, against SVG 2's text.
  • The clips guide's porting note for staggers covers a grid with fewer items than columns (#260): GSAP lays it out as one row of its items and spreads each over count - 1. A grid of one row whose origin GSAP puts off that row has no translation, measured across both axes. test_rival_stagger checks 832 of GSAP's cases.
  • The clips guide names every way a clip's positions differ from GSAP's timeline, each with the translation a port needs (#262). These are a child's delay, a start before 0, a callback, the end after an endless child, percentages and a label not yet added. For a child before 0, it says what plays at the clip's time 0. test_rival_position checks 400 of GSAP's timeline scripts.