Can anyone point me in the direction of any discussion on the source code behind the loopOut() expressions? In particular, I am interested in how the code uses the In/Out frame input parameters. I gather that what something like loopOut("cycle") is doing is creating a seamless loop rather than a repeat pattern--in which case the code itself would expect that the In/Out frames be identical.
I'm not sure what source code you're referring to, but loopOut("cycle") won't generate a seamless loop unless you set up the first and last keyframes to match in value and easing. Most of the time it will be a repeating pattern.
Thanks for the reply, Dan! By source code, I mean the actual code block that defines the loopOut() function. I think that you are right that the main confusion that I have been running across has to do with that distinction between a seamless loop and a repeat pattern.
A seamless loop is generated using just loopOut() because "Cycle" is the default. If the first and last frames are identical you will get a seamless loop because the loop will actually happen one frame before the last keyframe.
Imagine a clock with the second-hand rotating 360º in 30 frames. The first keyframe would be 0º, the keyframe at frame 30 would be 360º. If the second keyframe was repeated then the second hand would be straight up for two frames. The loop actually runs from 0º to 348º then on between frames 30 and 60. Did you follow that? It took me a long time to figure out why that works.
On the other hand, if you want to create a seamless video loop of that animated clock you have to render frame zero to 29, not frame 30 so you get the same seamless loop by looping the video by setting it to loop in file interpolation.
If you want to generate a repeating pattern you have to copy the first keyframe and then paste it one frame past the last keyframe. Try it for yourself with a simple animated text layer. Add this expression to a text layer.
Move down the timeline until the frame count is 10. Set an out point for the text layer, pre-compose moving all attributes to the new layer and trimming the new comp to the layer length. Add Time Remapping, move to the last time remapping keyframe, then back one so the 10 shows and set a new keyframe. Select the first time remapping keyframe and copy it. Select the last time remapping keyframe and paste. Now the first and last keyframes are identical again and you have created a repeating pattern instead of a seamless loop.
The code itself has no magic. It simply triggers normal keyframe evaluation similar to valueAtTime(), just eliminating a bunch of extra code that you would need otherwise to construct a loop. You are assuming too much there. It doesn't really care what the keyframes are. All it does is change AE's internal fluid time as a trigger criteria.