Development: Calling Spritesheet / DragonBones / Spriter / Spine / GAF (etc) developers

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 :slight_smile:

2 Likes

I am very interested, I should be able to contribute to Spine.

Right now I have a very janky implementation of movieclip in my Adobe Animate Atlas thingy.

It would be cool if I could get that to work with an actual movieClip instead of my janky one.

Also, I am available to put some elbow grease into Spritesheet if needed.

Here’s the current API:

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());
3 Likes

I don’t know if Swf’s MovieClip will improve, such as batch rendering.

If I can read Swf animation data, it should not be too difficult to work with this implementation.

It is available with the new update of openfL ? Or would I have to download it separately, being in test mode?

I’ll try with Spriter but I’m not sure of the benefits.

Is it time to make our own OpenFL editor to replace Animate?

This is a draft API being refined in the dev version :slight_smile:

Perhaps with this architecture you could invert the control on some of the behaviors, for example:

engine = new SpriterEngine(Assets.getText('assets/test.scml'), lib);
timeline = new SpriterTimeline(engine);

movieClip = MovieClip.fromTimeline(timeline);
movieClip.x = x;
movieClip.y = y;
movieClip.name = "uniqueId";
movieClip.gotoAndPlay("run");

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