Function Overloading in AS3

Why doesn't AS3 have function overloading

If there is anything I hate more than when actionscript doesn't do something I wish it would, it is when people complain about something they wish it would do. Sure, it would be nice if it incorporated every programming concept ever but that just isn't going to happen. In fact, this point is the same for every language out there. It sure would be nice if they all did everything but then there would only be syntacticular differences and that would be silly. Anyway, actionscript does not natively offer function overloading, and I've heard and/or read people complain about that from time to time.

Roll your own

Usually the reason you wish a solution existed natively is because you've used it before and you'd like to have the same ease writing the code. At least, if we follow the premise of not pre-optimizing code. So, if a language doesn't have that construct what do you do? Either find an alternate or roll your own. Today we are going to roll our own method for overloading functions in AS3 to allow for some of the benifits of native function overloading.

This isn't my idea

I have to admit, this isn't my idea. Back in the days of AS2, there was one library that did a lot of rolling its own solutions to constructs actionscript didn't provide. That library was as2lib by Simon Wacker and Martin Heidegger. I remember just reading the as2lib source code to learn different ways of doing thing. They had a solution for function overloading that I used as a basis for the AS3 code. I figured, AS3 had better reflection and introspection (as2lib had libraries for that as well) than AS2 so this should be fairly easy. In some ways it was and in some was it wasn't. That's a good thing because I learned a few things along the way.

Enough typing, where's the code

The code I wrote to allow this functionality is available at github. Usual rules apply, this code is just a proof of concept, for educational purposes only. Though I've written some tests, I make no guarantees.

Sample Usage

Sample usage is available in the Main.as file on github but I'll provide you with a taste here.

private function aFunction(... args):* {
    const overloader:Overloader = new Overloader();
    overloader.addHandler([String, Number], onStringNumber);
    overloader.addHandler([String], onString);
    overloader.addHandler([Number], onNumber);
    overloader.addHandler([int], onInt);
    overloader.addHandler([uint], onUint);
    overloader.addHandler([Boolean], onBoolean);
    return overloader.process(args);
}

private function onInt(value:int):void {
    trace("We got int: " + value);
}

private function onUint(value:uint):void {
    trace("We got uint: " + value);
}

private function onBoolean(value:Boolean):void {
    trace("We got Boolean: " + value);
}

private function onNumber(num:Number):void {
    trace("We got number: " + num);
}

private function onString(str:String):void {
    trace("We got string: " + str);
}

private function onStringNumber(str:String, num:Number):void {
    trace("We got string, number: " + str + ", " + num);
}

// then to use the overloaded function
public funciton Main(){
    aFunction("Hello World", 13); // output: We got string, number: Hello World, 13
    aFunction(1 == 0); // output: We got Boolean: false
    aFunction(13); // output: We got uint: 13
    aFunction("Goodbye"); // output: We got string: Goodbye
}

A couple notes and gotchas that you might be wondering about as you look at this code.

  • Numerical arguments are automatically converted to any numerical class asked for, as long as the value can be of that type.

    • For this reason I made it test numerical explicitness in the following order: uint before int and int before Number.

      • Therefore if their are two matching functions due to numerical parameters a method using uint will be considered more explicit than a method using int or number.
    • You can't force a numerical type. I tried several methods and none worked.
  • If your overloaded function returns void you will need it to return * so it will compile without error.
    • EDIT: not true, just don't use a return statement
  • Because AS3 uses method closures most of the time, instead of anonymous functions, you usually don't have to worry about function scope. This is mostly a good thing. Watch out if you do use an anonymous function though. It will most likely work correct but there are a few ways it could fool you.
  • I wanted to do introspection on the method signatures so you didn't have to send in the values but, alas, method signatures do not seem to be available via reflection. From what I could figure out from studying the Tamarin code, they are part of the functions Trait object which isn't available from actionscript (and may go away in the future according to the documentation). This means you have to put them in as Arrays.

Not True Overloading

Okay, so this isn't true overloading but it gets us a little of the way there. The only solutions available online use the ellipsis (...) method but you still have to write the boilerplate logic to provide type checking. Also, what happens if there is no match? With my code you at least get an error telling you what went wrong. It isn't compile time but it can help with debugging.

Also, look at what this solution actually provides. It doesn't have to be used for function overloading. It could be used anywhere you want to handle differing types of data passed in as arguments. I could envision this helping to trim down some nasty if and/or switch statements. Take a look and see what it could do for you.

Conclusion

I find the Function class and Function objects fascinating in actionscript. Back when I dug into the different types of Delegate classes for AS2 (I actually made a similar one for AS3 at one time) I learned a lot about the language as a whole. Scope used to be the bane of my existence and then I finally understood it. Scope may not be an issue anymore in AS3 but there is still quite a bit to learned about the language from studying Function objects. The very fact that a Function is an object that can be passed around in actionscript is a very nice thing. Not all languages allow that type of functionality. I guess if you are using those, you'll have to roll your own function passing solution.

Under the mask but I didn't ask - Flash Friday

Masks in the flash IDE are an interesting thing. You may have noticed that masks created in the IDE are not found in the normal "mask" property found on a movieclip. This is because it isn't a normal mask. The mask is working on a layer instead of on a single DisplayObject. This little quirk causes some interesting behavior that you may never have noticed before. If you have a MovieClip with a mask as a top layer of the timeline there is some strange behavior when you addChild to that MovieClip. The added content gets placed under the mask. Wait! What? The added content gets placed under the mask. You may not have noticed this behavior in the past because you may never have done it, you may not have your item cut off by the mask or you just might not have been able to figure out why you couldn't see your item. However, it is happening. [ad#Google Adsense] Another twist on this phenomenon is that if the mask isn't the top layer but your remove the items that are on the top layer then add a DisplayObject. Well, in that scenario your new DisplayObject is also placed under this "Layer Mask". I found this out today when I had a top layer above a mask that was a TextField. For a localization project I'm working on I had to wrap the field in a wrapper class that then gets added back where the textfield was. I was trying to figure out why the textfield was now appearing like it was under the mask. The answer...because it now was.

So how did I deal with this? How can you deal with this if you find it happening? First off, it might be an easy thing to just restructure your timeline so the mask isn't on top. If that isn't possible, the hack easy fix is to add a blank MovieClip symbol to the layer above the mask layer. That is what I did for this asset and all is well.

I haven't extensively tested this but my guess is the quirk may exist if you add something to any layer right above a "Layer Mask" it will placed under the mask. Is this something you have experienced? How have you worked around it? Have you used it for any type of effect?

I don't believe you really want to count on this behavior for anything as I don't believe I've seen it documented anywhere. Someone at Adobe might read my blog :) and decide this isn't appropriate behavior they might fix it in Flash Player 20 or something.

Flash Friday Refactored - IS_IN

A while back I wrote a proof of concept isIn functionality injector that seemed to work fairly decently. I even wrote some tests for it that it passed with flying colors. Being a proof of concept I never really used it and never ran into the danger of using that functionality. Recently I downloaded the trial for FDT and since it doesn't have the same type of FlexUnit integration that FlashBuilder 4 has I had to get my tests working differently. When I got the tests up an running my tests for the isIn functionality blew up in spectacular fashion. They didn't just fail, the took the whole unit test display down with them. This was the same class and tests that passed cleanly before. What happened?

It turns out messing with the prototype of Object to solve a problem is like fighting fire with a nuclear explosion. It will probably work but cause serious problems throughout the system. So, following the test driven development methodology of red, green, refactor I saw that it was a time for a refactor. Well that and it was now a red test that I wanted to make green.

I came up with a solution that I think is better. It is more flexible than before, since you can select the class you want to add the functionality to. Even better, you can remove the functionality after you add it. Since I've begun to move my code over to GitHub you can find the new code over at https://github.com/darylducharme/Ducharme-Media-Code/tree/master/src/cc/ducharme/utils. The new test class is available at https://github.com/darylducharme/Ducharme-Media-Code/blob/master/test-src/utils/IsInTests.as

You may notice that the last test - dictionaryEnumerationTest()  at this time - is new. This is the test that checks the problem that I found that was not being tested before. If you are writing tests and find a hole in your tests later, it is always recommended to add new tests to keep you from having the same problem in the future.

Hopefully, someone out there can learn from my mistakes on this occasion. Also, the new isIn class and its static functions are a whole lot more useful than what I had written before. Perhaps someone out there can put it to good use.  What do you think?

Transitions and the Transition Manager

With Flash CS4 ( and CS3 for that matter ) comes a great utility for simple visual effects, the Transition Manager and accompanying transitions. With this tool you can use some common transitions without much complex coding on your side. The following is a list of the available transitions.

Transitions can be used by themselves or mixed together for an even more professional look. And all this is very easy because of the power and simplicity of the Transition Manager class. Using the class is very simple. The following code performs a simple fade in on an imaginary MovieClip instance named myClip.
import fl.transitions.*;
var transitionMgr:TransitionManager = new TransitionManager( myClip );
var params:Object = new Object();
params.type = Fade;
params.direction = Transition.IN;
var transition:Transition = transitionMgr.startTransition( params );
The above code could also be done with the static start() method, like so:
import fl.transitions.*;
var params:Object = new Object();
params.type = Fade;
params.direction = Transition.IN;
var transition:Transition = TransitionManager.start( myClip, params );
Using the static start() method is a bit cleaner. However, if you need to do multiple transitions to the same movieclip the first method is best.

[ad#Google Adsense]

Using Parameters

The two transition methods both take a parameters object, but you might be wondering what goes in the object. That depends on a few things and here are some options.

  1. The type is required - enter one of the 10 above.
  2. Other common properties for all transitions include
    1. direction - choices are Transition.IN and Transition.OUT ( default is Transition.IN )
    2. duration - this is measured in seconds
    3. easing - This is a function. I believe the default is None.none;
  3. You can add parameters specific to the fade type you are using( i.e. numStrips for a Blinds transition )

When does it end?

When looking at the documentation for the Transition and Transition Manager classes, there appears to be a problem. If you want to do something when the transition(s) are done there doesn't appear to be any events that tell you when this occurs. The truth is there are events that get fired, the documentation is just lacking. The events that get fired are of type flash.event.Event and there are no constants to give you any auto completion help.

For the transitions the following events may be fired:

  • "transitionInDone"
  • "transitionOutDone"
  • "transitionProgress"

The TransitionManager fires the following 2 events

  • "allTransitionsInDone"
  • "allTransitionsOutDone"

Example

With all the above in mind I thought I would show each of the different transitions and the events that fire. Each transition uses all of its defaults, but you do get to choose the direction so you can see the different complete events :)

One Last Thing

The Transition classes unfortunately are only coded to work with MovieClip instances. For many people who don't code in MovieClips you may have to find a different solution but for most users of Flash CS4+ this shouldn't be a problem. [ad#Adobe Banner] If you liked this post please subscribe to my RSS feed and/or follow me on Twitter. If you only want to see my Flash Friday posts you can follow the subscribe to the Flash Friday feed. How's that for alliteration :) Until next time keep on coding.

wmode:gpu not a magic bullet

At my current work, Provis Media Group, we do a lot of video for the web. We've had a lot of success with larger format video than is usually delivered via the internet. When Flash Player™ 9.0.115 came out allowing fullscreen h.264 video delivery things really took off. Quality went way up and we were able to deliver 720p+ content over the internet. In full screen it looked great. However, when we shrunk a video smaller than its true size some artifacting would occur. Really, it wasn't that terrible but we pride ourselves on the quality of video we deliver, especially since most of it is done in house. When flash player 10 came out we noticed 2 new wmodes, direct and gpu. Both were suppose to affect drawing performance on the screen and we thought gpu mode should improve the quality of our videos. In order to be sure we had to test it and compare it to the default mode that we almost always use.

Test after test proved that there really wasn't any noticeable difference. In fact, wmode=gpu didn't provide any noticeable playback difference but it did affect the player. [ad#Adobe Banner] The more we read, the more it sounded like wmode=gpu really wouldn't do much for most people until Flash Player™ 10.1 ( currently in beta 2 version on Adobe labs ). Installing Flash Player 10.1 did improve performance on the CPU ( which is awesome ) but their still wasn't a difference from the default.

In the end the best thing to do with our video was to turn smoothing on. This actually made a dramatic improvement. In Flash Player 10.1 you get enough of a performance increase to make this work on even slower computers than before.

So wmode=gpu still may not be a magic bullet unless you control the playback platform but turning on smoothing gives you good performance if you are having artifacting when your videos get resized. You still need to be concerned about cpu performance ( for now ) but flash player 10.1 will really improve that.

If you have had different results or even the same, I'd love to hear your experiences. If you celebrate Christmas today then Merry Christmas and to everyone Seasons' Greetings and Happy Holidays.

Decreasing load times with RSLs

Recently, Adobe released version 3.5 of the Flex SDK. I updated a project I was currently working on from 3.3 to 3.5 and I had to reset up my runtime shared library (RSL) for the project. This got me thinking that many people don't know how to properly use RSLs. The world of flex development is better if we all use the the SDK RSLs so that is the topic of today's post

Read More

Embedding Fonts in Flex Builder Using the Flash IDE

[ad#Adobe Banner] Flex is great for building rich internet applications quickly. Building an application quickly is nice, but to give your application that truly professional touch you need to customize the look and feel of your app. In order to fully customize the look and the feel you will need to use a font that's different than the default serif font that is used everywhere.

The flash player affords you the opportunity to embed many non standard fonts into your app, something that sets it apart from AJAX applications that need to rely on web safe fonts. In the flash IDE this is as easy as setting the font in the properties panel and selecting which character from that font which you want to embed. In a Flex app, things get a little trickier - especially if you want to use a non True Type font, which is the only type it can import natively. However, if you have the Flash IDE you can use its simplicity to get any font you can use in Flash into your Flex app.

The process is broken up into two steps.

  1. Create a SWF with the font(s) you need embedded in it
  2. Add Style (CSS) info to your Flex project that imports the font into your Flex project

Character Embed Dialog in Flash

Step one starts with the simplest of FLA files and can be created with earlier versions of the Flash IDE  (so you can use Flash 8 or MX2004 if that's all you have). I recommend using a separate FLA for each font you want to embed, that way it is easier to catalog, store and reuse in other projects. Create 4 dynamic text fields. Each text field is for the different versions of the font so you should have:

  • normal
  • italic
  • bold
  • bold italic

You need to make sure you set up all 4 text fields to embed all the glyphs from the font you will need.  For most western languages Numerals, Punctuation and Basic Latin should cover all the glyphs you will need. Once again, make sure to set up the character embedding for all 4 text fields. If you notice certain parts of your flex document using the default font you may not have set up character embedding. You can of course leave out any of the 4 ( ie italic and italic bold ) that you aren't going to use but if you are going to reuse the SWF I would do all 4.

Once you are done setting the character embedding for all 4 text fields, publish the file to a SWF. [ad#Google Adsense] The second step of this process is to add Style to your Flex project that imports the font into the project. That's as simple as adding an @font-face entry to your CSS file or <mx:Style> block. At first you simply give it the path to your font SWF and the name of the font ( ie Futura Book, Calibri ).

@font-face
{
src:url( "path/to/yourFont.swf" );
fontFamily:"Exact Name of Font"
}

You also need to add an @font-face entry for each version of the font you want to use. So if you also wanted to use the bold version you would add the following:

@font-face
{
    src: url( "path/to/yourFont.swf");
    fontWeight:"bold";
    fontFamily:"Exact Name of Font";
}

After you are done adding the appropriate @font-face entries you can style any component you need to or you can style the entire application with your font.

Application
{
    fontFamily:"Exact Name of Font";
}

There are a couple other ways to embed fonts, and if you don't have a version of the flash IDE those are the only way to go. If there is enough interest I can cover those in comments or another post. However this is by far the simplest, it allows you the ability to embed non True Type fonts and you can reuse a font more quickly in the future. [ad#Adobe Banner] If you liked this post please subscribe to my RSS feed and/or follow me on Twitter. If you only want to see my Flash Friday posts you can follow the subscribe to the Flash Friday feed. How's that for alliteration :) Until next time keep on coding.