Starling 2.2

Daniel Sperl on June 27, 2017

Hard to believe, but we are already halfway through 2017! Since I spent so much time with the Starling Handbook, there hasn’t been a new official Starling release for quite a while. With the handbook out of the door, however, I could finally put on my developer hat again – I had really missed it!

Today, I’m proud to present the Starling Framework 2.2, and I think it’s not exaggerated to say that it was worth the wait. This version adds a lot of polishing to the 2.x line and introduces several nifty new features. Let’s dive into it!

Image by James Barker

Inverted Masks

I’m starting with a contribution by Ehsan Marufi. He dove deep into Starling’s stencil mask implementation and actually managed to add support for an often requested feature: inverted masks!

Normally, a mask ensures that only those parts of a display object are rendered that are inside the shape of the mask. With an inverted mask, it’s the other way round: only the parts outside the mask shape are rendered.

If you already worked with masks (and, honestly: who hasn’t?) this feature is really super easy to use. Just create your mask as usual; then enable the property maskInverted on the masked display object. Like this:

var object:Sprite = createSprite();
var mask:Quad = new Quad(100, 100);
object.mask = mask;
object.maskInverted = true;

Couldn’t be any more simple, right? Ehsan even set up quite an amazing live demo that proves that his code works even with nested hierarchies. Thanks a lot for that great addition!

Stronger Blur

The existing implementation of the BlurFilter had two limitations that always bugged me:

  • A really strong blur effect could only be achieved with a massive number of draw calls.
  • When animating the blur with a tween, the strength did not grow smoothly.

For this reason (and thanks to a tip from my friend Bernhard Pichler from StageXL), I had another look at the filter implementation. By changing the way how the subsequent render passes are combined, I was able to achieve a higher blur effect with much fewer passes. The sample below shows what is possible.

Not too bad, right? Just beware that this means that blurs in your existing projects will look slightly different, so you may need to check if the output is to your liking. However, since you’re getting more blur out of fewer draw calls, I hope you agree that this is a small price to pay.

Binding Scale9 Grids to a Texture

Scale9Grids are a great way to create flexible user interface components and save texture memory at the same time. However, it’s a little cumbersome to apply the grid manually to all respective images. After all, a specific scale9 texture typically always requires the same scale9 grid, anyway.

Thanks to an idea by Kevin Foley, you can now easily automate this workflow. A new static method on the Image class allows you to bind a scale9 grid to a specific texture. From that moment on, whenever you assign that texture to an image, the scale9 grid will be set up automatically.

var texture:Texture = assets.getTexture("button");
var scale9Grid:Rectangle = new Rectangle(4, 4, 52, 52);

// call this once when your textures are ready
Image.bindScale9GridToTexture(texture, scale9Grid);

var image:Image = new Image(texture); // applies grid
var button:Button = new Button(texture, "Press me"); // also applies grid

Note that even the Button class will be updated with the correct grid: that’s because it uses the Image class internally.

I figured that a similar feature would also be useful for pivot points – or even for arbitrary setup code. For example, you might want to disable texture smoothing for all images that use a specific texture!

// Automated pivot point setup
Image.bindPivotPointToTexture(texture, 35, 20);

// Automated setup of pretty much anything
Image.automateSetupForTexture(texture,
    function(image:Image):void
    {
        image.textureSmoothing = TextureSmoothing.NONE;
    });

This can potentially simplify a lot of boiler plate code! (It seems we just lost a couple of readers – they are off to do some refactoring.)

Asynchronous Bitmap Upload

AIR 24 introduced a feature that many developers have been eagerly waiting for (myself included): asynchronous uploading of bitmap textures. This means that you can let the runtime create a texture object in a background thread while rendering goes on undisturbed (ideally, with no hiccups).

Starling supports this feature via the new async parameter in the respective Texture creation method.

var bitmap:Bitmap = getBitmap();

Texture.fromBitmap(bitmap, false, false, 1, "bgra", false,
    function(texture:Texture):void
    {
        addChild(new Image(texture));
    });

If you find that familiar, that’s because it works just like it always did for ATF textures.

There is only one caveat: the feature is currently not 100% stable, especially on Android. For this reason, I decided to better let developers manually “opt in”. My recommendation: activate it on a per-platform basis. For example, it does already work fine on iOS.

Texture.asyncBitmapUploadEnabled = SystemUtil.isIOS;

Don’t worry: the code will work just the same, whether the feature is enabled or not. The async callback is guaranteed to be executed, it’s just that the internal upload won’t really be asynchronous.

I’m optimistic that Adobe will have this ironed out soon, however. When that’s done, I can enable this per default.

DrawToBitmapData

Thanks to some fixes in recent AIR versions, I could move the method drawToBitmapData from the Stage to the DisplayObject class. This means that it’s now easily possible to store any display object in a standard bitmap data object. You could use this e.g. to create a context-loss surviving snapshot of a RenderTexture.

var bitmapData:BitmapData = image.drawToBitmapData();

Field Agent

I’m a huge fan of the possibilities coming with distance field rendering. It’s not only useful for fonts, but also for monochrome icons and many other vector-like graphics.

One reason that it’s used so rarely might be that it’s hard to find good tools to create such textures. That’s why I added a new command-line script to the utils folder of the Starling repository. It’s called “Field Agent”.

In a nutshell, the field agent converts any arbitrary black-and-white texture into a distance field texture. I’m describing it in detail in a special chapter of the Starling Manual. Definitely check it out!

Summary

Besides those major new features, you’ll find numerous small additions, optimizations and bugfixes in the changelog. All in all, this release should contain something for everybody – please give it a try and tell me what you think about it! The comments section below is eagerly awaiting to serve your posts.

Special thanks goes to all the community members who helped out with pull requests, feature suggestions, and bug reports. It’s impossible to name everybody, but I’d like to specifically mention Ehsan Marufi, Keven Foley, Alexander Mokretsov, pbalmasov, Robert Carone, Josh Tynjala, vroad, 5k0rp, neuronix, and bwhiting (in no particular order).

Yes, that’s quite an impressive list of people! Thanks a lot, guys – this release wouldn’t have been possible without you.