6. Progressors
Progressors are another category of animations somewhat similar to followers.
6.1 Progressors
We just saw the Rotated example using Lerp, but it was a bit clunky. Lets see how progressors can help with that.
DEFINITION An animation is said to be a progressor if it takes in input iterators and modifies one or more of them. This is useful for abstracting repeated logic.
We can use a progressor to handle the boiler plate of Lerp + Rotated for us:
tree lerps = Square:
center: LEFT
width: 0.5
tag: {}
stroke: BLACK
func Rotate(mesh&, rotation, time) = identity:
var ret = {}
/* first add rotated functor wrapper */
mesh = Rotated:
mesh: mesh
rotation: 0
ret += Set:
vars&: mesh
/* linearly interpolate rotation */
mesh.rotation = rotation
ret += Lerp:
vars&: mesh
time: 1
element: ret
p += Rotate:
mesh&: lerps
rotation: 5 * PI / 4
time: 1
/* at this point lerps = Rotated {...}, that is, the iterator was modified */
/* also, theres the rotation animation */
IMPORTANT By definition, progressors modify their input iterator. Therefore, you should be careful when using them because they may have unintended side effects. For instance, in the above example, it may be unexpected that lerps is no longer of type Square, but instead of type Rotated.
The standard library does not provide that many progressors (mostly because I felt that would be too opinionated), but we just saw how easy it is to create them if you prefer.
Exercise: Create Shift and Scale progressors.
Another common use case is for hiding. For instance, we can create a FadeOut progressor as followers:
func FadeOut(mesh&, time) = identity:
var ret = {}
mesh = {}
ret += Fade:
meshes&: mesh
time: time
element: ret
6.2 Progressors vs Followers
Progressors and Followers aren't all that different, with the one difference being that progressors are expected to modify their input. However, this difference means that followers are generally easier to reason about (since there are no side effects). On the other hand, progressors help remove boilerplate and are generally easier to write. Finally, some animations necessarily need to use progressors and cannot be done using followers (we'll see LerpSubset and TransformSubset as examples in the future), but these aren't that common.
Use whatever works best for your workflow.