There is a new Timeline API in the works in the OpenFL develop branch which enables support for abstract timelines plugged into MovieClip – and it even works on the Flash target!
var timeline = new SpritesheetTimeline(bitmapData, spriteSheetData);
var movieClip = MovieClip.fromTimeline(timeline);
movieClip.gotoAndPlay(100);
In order to make this a big success I think we need to try and use the feature from more sources of timeline animation sprites and see if the API is ready for primetime, the big benefit of integration is that all MovieClip features (frame scripts, stop, play, labels, scenes) will be provided by OpenFL so the library will only need to know how to render.
Please contact me on the forums or on the OpenFL Discord server if you are interested in trying this out and helping out
package openfl.display;
/**
The Timeline class is the base class for frame-by-frame animation.
Timeline is an abstract base class; therefore, you cannot call
Timeline directly. Extend the Timeline class in order to provide animation
compatible with the MovieClip class.
It is possible to create a MovieClip with a Timeline using the
`MovieClip.fromTimeline` static constructor.
**/
class Timeline
{
/**
The frame rate of the Timeline. The frame rate is defined as
frames per second.
The frame rate can be different than the Stage `frameRate` and will
playback at an independent rate, or the frame rate value can be
`null` to match the rate of Stage.
**/
public var frameRate:Null<Float>;
/**
An array of Scene objects, each listing the name, the number of frames,
and the frame labels for a scene in the Timeline instance.
**/
public var scenes:Array<Scene>;
/**
An array of scripts to be run when the playhead enters each frame.
**/
public var scripts:Array<FrameScript>;
/**
Called internally when the Timeline object has a movie clip attached.
This is an abstract method, so it should be overridden with an implementation
in child classes.
@param movieClip The parent MovieClip being attached to this Timeline
**/
@:noCompletion public function attachMovieClip(movieClip:MovieClip):Void {}
/**
Called internally when the Timeline object enters a new frame.
This is an abstract method, so it should be overridden with an implementation
in child classes.
Do not rely on this method being called for every sequential frame. Due to
frame rate as well as default looping at the end of timelines, the `frame`
value represents only the current frame required.
@param frame The current frame
**/
@:noCompletion public function enterFrame(frame:Int):Void {}
}
It is an abstract base class (similar to DisplayObject) so it is extended in order to provide support for a new timeline format.
Here’s a basic example:
import openfl.display.FrameLabel;
import openfl.display.FrameScript;
import openfl.display.MovieClip;
import openfl.display.Scene;
import openfl.display.Timeline;
class MyTimeline extends Timeline
{
private var clip:MovieClip;
public function new()
{
super();
frameRate = 24;
scenes = [ new Scene("", [ new FrameLabel("start", 1) ], 100) ];
scripts = [ new FrameScript(function(mc) mc.stop(), 100) ];
}
public override function attachMovieClip(movieClip:MovieClip):Void
{
clip = movieClip;
}
public override function enterFrame(frame:Int):Void
{
var alpha = frame / 100;
clip.graphics.clear();
clip.graphics.beginFill(0xFF0000, alpha);
clip.graphics.drawRect(0, 0, 100, 100);
}
}
I want to work on performance, creating an API that feels nice and simple to use, and which does everything we would need from a custom timeline behind MovieClip
The above sample could be instantiated like this currently (on non-Flash targets)
var movieClip = new MovieClip();
movieClip.attachTimeline(new MyTimeline());
addChild(movieClip);
On all targets (Flash included) the following currently works:
var movieClip = MovieClip.fromTimeline(new MyTimeline());
On the dev side, we can re-use logic to handle playback, frame scripts, loops, scenes (etc) and the client side the difference between a SWF MovieClip and Spriter/Spine/DragonBones/Spritesheet/etc MovieClip would be at construction time but not in its use