Project Panel update for CS5

We have made some changes to the free Project Panel Update that we released last year, which makes it compatible with Flash CS5.

Unfortunately, CS5 now overwrites the project panel files each time it launches, so this new version installs as a completely separate panel, which was have renamed “gProject”, a nod to its humble roots.

For more information on what the upgrade brings to the Project panel bundled in Flash, please read the original post. Since it is free, we can’t promise any support, but feel free to report any bugs using our support form.

You can download the gProject panel for CS4 and CS5 by clicking here.

FITC San Francisco

I have to admit, I’m excited about FITC San Francisco on August 17-19. The conference has an amazing line up, including my personal Flash hero, Yugo Nakamura. It’s also in an awesome location. SF is the heart of the Flash world, and there’s lots of cool innovation happening in the interactive space. I’m looking forward to hanging out with friends in the area, and catching up with clients.

I’ll also be debuting a brand new talk, titled “ADHD FTW, LOL!!”. It’s a (hopefully) fun talk about the random experiments, applications, and libraries I build while I’m procrastinating or bored. It’s basically about how to turn your distractibility into a strength. I’ll be showing work from roughly the last year, including some stuff I’ve never really shared before. After a couple of years of technical sessions on topics like code optimization, development process, and code standards, it’ll be kind of nice to present an inspirational talk!

If you’re thinking of going, and haven’t bought tickets yet, you can get a 10% discount using the code “gskinner” on the FITC website. Hope to see you there!

Some Thoughts on TLF & FTE

I’ve been thinking a lot about TLF over the past few months; not just about how to use it, what features I like, or what bugs I’ve encountered, but about the philosophy and underlying model it’s built on. I’m hoping that by sharing these thoughts and getting input from the community, I can provide useful feedback to Adobe both about TLF and their future efforts.

I’m sure I’m oversimplifying in some places, and completely wrong in others. Please excuse any errors.

Background

Flash Player 10 introduced the flash.text.engine.* (FTE) package, which contains classes that provide low-level text handling capabilities. FTE is extended by a set of ActionScript 3 classes in the flashx.textLayout.*, known as the Text Layout Framework (TLF), which is shared between Flex and Flash Pro. These classes provide abstract FTE somewhat, but remain fairly low-level.

Flash Pro exposes TLF through a new TLFTextField component, which provides IDE integration and a high-level AS3 abstraction that closely mirrors the TextField API, but with a broad range of new text and typography features. These include multi-column text, text threads (aka linked fields), right to left and vertical text, and a host of typographical enhancements.

The Flex 4 framework exposes TLF through 3 primitives: Label, RichText, and RichEditableText. These provide increasing levels of capability. Label displays a single line of text with a subset of formatting options. RichText supports multiline text with inline graphics and full formatting. RichEditableText adds links, editing, scrolling, and selection. Flex does not have support for text threads.

Philosophy

TLF illustrates a philosophical shift in API development for Adobe. With TLF Adobe chose to expose only a very low-level player API, then build a “standardized” higher-level AS3 API on top. The reasoning behind this appears to be to reduce player size, and facilitate development of the TLF libraries without a dependency on player updates. This means developers can utilize new TLF features as they are released without having to wait on a new version of player to achieve acceptable penetration.

The intent is good, but I’m not convinced it is the best approach in this case. With virtually no exceptions, text is a core element of every project built on the Flash platform. Making core text capabilities dependent on an ActionScript library introduces a variety of issues that I personally feel outweigh the advantages listed above.

File size

The core TLF library weighs in at about 160kb. This is exported as a signed RSL (.swz) beside your SWF. This means that once a user downloads the .swz for a specific version of TLF once, it should be cached locally and reused whenever the library is subsequently used, including on other domains.

This is nice, but if TLF is the future of text in Flash, and text is core to all experiences, it invalidates any benefit to player size. If all users will need to download the RSL anyway, you’re just distributing the problem. I’m also under the (perhaps mistaken) impression that the functionality would be smaller if implemented natively in the player.

Even with the RSL, using a TLFTextField in Flash Pro introduces an additional 60kb to your SWF. This is a pretty big hit for just putting hello world on the stage, and makes TLF unusable for banners and other experiences with file size restrictions. Exacerbating this, Flash exposes TLF as just another text option, not as a component, which makes its cost unclear.

Performance

Because TLF is implemented in ActionScript, it suffers from the same performance problems and memory issues as other AS3 code. Performance in AS is magnitudes better than it used to be and 10.1 brought significant improvements to memory use. However, AS performance remains *much* slower than native code (10-100x in many cases), and memory use is still much higher.

TLF suffers greatly from this. It uses far more CPU to manipulate and display text than TextField, to the extent that Adobe has recommended not using it for mobile devices, and is considering development of a light-weight implementation of TLF specifically for devices. I find it disappointing, and a little ironic, that two of the most important new initiatives for the Flash platform, developed in parallel, are incompatible.

TLF also consumes much larger amounts of memory than TextField. Beyond the memory cost of the AS framework itself, it has to generate huge AS object models describing text structure and layout. It also generates large numbers of display objects (TextLine) to display the text.

This is made even worse by the fact that in TLF all of these objects are generated and maintained for all text in a scrolling text region, not just the visible text. While only the visible text is rendered to screen, there is still a display cost for every TextLine instance as it has to be iterated and culled from the scroll rect. This means there is a high cost for both memory and performance associated with large amounts of text in a scrolling text area. In TextField, this cost is very low.

Flash performance is already a hot enough topic. TLF’s AS implementation is going to make it worse.

Consistency & Complexity

TLF represents the first major collaboration between the Flash Pro and Flex teams. This collaboration is a *great* thing!! I cannot emphasize this enough. These teams really need to work together to create a unified component framework and integrated authoring platform, and I hope that TLF provided an opportunity to really test these waters. Unfortunately, I don’t think they went far enough.

Right now, Flash Pro has a very decent high level abstraction of TLF with TLFTextField. It exposes an almost identical interface to TextField with a lot of nice additions. It’s easy to work with, and simple to extend.

Flex, regrettably, does not appear to have any similar high-level text control built on TLF. Even TextArea lacks most of the functionality of a TextField. To achieve even very simple tasks like finding the position of a character, you are forced to wade through the TLF library, and dabble in FTE.

At this point, I am concerned it will be difficult to retrofit these capabilities into Flex’s spark architecture. I also wonder if these features are missing because of their performance implications when implemented in AS.

Versioning

I understand the benefit of being able to version TLF separately from the player, but leveraging it introduces another set of problems. Firstly, it reduces the efficacy of the cached RSL – it has to be downloaded and cached for every new version. It also has obvious implications for team development, custom controls, and commercial or OSS libraries / components that target TLF. None of these are huge issues (except perhaps the last one), but they still reduce the overall benefit of the model.

Thoughts

As someone who has messed around pretty deeply with the TextField APIs, trying to force it to do some of the things that are possible with FTE (multi-column, decorations, etc), I appreciate the inclusion of low level text APIs. However, I think text is too integral to interactive media to not make usable and performant APIs a core part of the platform.

What I would really like to have seen, was the same low-level FTE API, extended with a player level API for text layout similar to TLF. This could be built on a set of interfaces (as it already largely is) to make it easy to write alternate AS3 implementations of these classes. Further, I would have liked to see a usable text field implemented at the player level on top of these APIs, with most of the functionality of TLFTextField. It would expose an ITextField interface which TextField would also be retrofitted to support.

Ideally, this would provide greatly enhanced performance and reduced memory footprint, while still enabling developers to dig deeply and create custom implementations. It would guarantee a consistent API and implementation between Flash and Flex and even allow developers to work with many aspects of text without knowing if the container is TLF or a TextField by typing as ITextField. While it would increase player size, it would reduce the overall bandwidth spent on downloading TLF related elements. Adobe could even update some aspects of TLF between player versions by providing AS3 extensions of the built in classes.

It may be too late to do this, but I don’t think so. The current player APIs would not have to be changed, which means current content wouldn’t break. The current TLF APIs and a TLFTextField equivalent could be implemented natively in the flash.* package, without breaking the current AS3 versions. A future version of the Flex framework could migrate to use the native API with minimal disruption. Likewise, Flash Pro’s TLFTextField could be stripped down, and become viable for banners and mobile.

If this can’t be done, I’d like to at least see some engineering time spent fixing and enhancing TextField, so that we can continue using that when TLF simply isn’t the best choice.

Even if it is too late to fix (in my opinion) TLF, I think it’s important to raise discussion around Adobe’s new philosophy to help steer future decisions. I don’t think Adobe should go as far as MS has with Silverlight, where controls/components are embedded in the player, but I do think that elements that are as core as TLF belong in the player.

There’s a lot more I’d like to say, but this is getting long, and I think it covers the most pressing topics. I’d love to hear what you think in the comments.

Ultra Simple Output Class

Lately I’ve been messing around with Flash on devices and in other “new frontiers”. It’s fun, but sometimes getting debugging working is hit or miss. To address this, I wrote an ultra simple class for tracing to a text field. It’s nothing fancy, but that’s the point – it’s simple (~15 lines of code), tiny (~0.5kb), handy (at least for me), and works well, so I thought I’d share.

To use it, simply drop Out.as into your class directory. Set an output text field when your app starts up:

Out.textField = outFld;

You can also specify a maximum number of characters to retain, so that old traces will be deleted as new ones are added.

Out.maxLength = 1000;

From anywhere in your application you can call Out.trace(value). This will trace the value normally, append it to the end of your text field, and scroll the text field to the end so that the latest trace is always displayed.

Out.trace("hello");
Out.trace("count: ",count); // supports multiple params

Finally, if you want to do something more custom, you can override Out.handler to use your own function.

function log(...rest:Array):Boolean {
  trace("logging: "+rest.join(","));
  // ... etc.
  // only write to text field if first param (ex. priority) is > 1:
  return rest[0] > 1; // returning false prevents it being written to Out.textField.
}
Out.handler = log;

You can download the Out class here. It is licensed under the MIT license.

Androideroids

There’s a lot of buzz around multi-screen experiences lately, where an application or game is available to you on multiple devices (ex. web, PC, mobile, TV, etc). Recently I’ve been fascinated by the idea of using these “multiple screens” together to create a single experience.

The first result was my Nexus One Gas Pedal which I posted last week. Following that, I wanted to do something that was more accessible, and allowed for more players, which led to the concept for Androideroids.

Androideroids is a prototype multiplayer asteroids game in which each player uses an Android phone as their game controller. Player’s can see a top down view of the game on the main screen (which could be a PC, TV, or projected in a public space), and a first person view with their health and score on their phone. The top down view is great for navigating, and first person view comes in handy for aiming during dogfights. Player specific sounds are played on the phone, whereas general sounds are played on the host.

This has lead to the development of what I feel is a strong framework for creating public installations and experiences that will allow smart phone users (on multiple platforms) to connect in an adhoc fashion.

When players launch the generic LANPad application on their phone, it finds and connects to the game host. The host sends the client a “surface” SWF which defines how the game will look and act on the phone.

The surface SWF sends messages to the host indicating UI input, the host interprets these, runs game logic, and sends back a message updating the game state on the phone.

Here’s a rough video on the project:

Continue reading →

AIR for Android Wireless Slot Car Gas Pedal

Recently I’ve been trying to carve out more time to play with technology – something I’d been neglecting sorely, despite constant admonitions (1, 2) to others to always make time to play.

One of the first results of this is a library for creating peer to peer LAN connections between AIR applications, with a strong focus on mobile to desktop applications. I’ll go into more depth about the LAN library in a future post, but for now I wanted to share something I built on top of it… the Nexus One Wireless Slot Car Gas Pedal.

Check it out in the following video:

Continue reading →

Quick Way to Set Props on a New Instance

I recently posted a feature request for AS3 asking for property initialization for instance construction. If you want details, check out bug #ASL-69.

In one of the comments, I referenced an existing way to quickly set properties on a new typed object, and thought it might be worth sharing. It’s super simple, but might prove useful.

Simply put the following code into a “setProps.as” file in your class path:

package {
public function setProps(o:Object, props:Object):* {
for (var n:String in props) {
o[n] = props[n];
}
return o;
}
}

Now, from anywhere in your code, you can quickly set multiple properties on an object. This can be handy when creating new instances. For example:

addChild( setProps( new Sprite(), {x:200, y:200, alpha:0.5, name:"bob"} ) );

This obviously isn’t type-safe, and it won’t provide compile time errors if you get a property name wrong. For small projects with short timelines, or just playing around it can make it easier to hack things together, but I don’t recommend it for larger or more formal projects.

The goal of my feature request was to enable similar ease of use, but with type safety, compile time errors, and full IDE support. Feel free to vote for it here.