Archive for 2009

Visual Reflections in ActionScript 2

Monday, November 23rd, 2009

Making a reflection is not that hard, but getting it to work right with scaled clips with weird registration points out of the box was a little harder.

Anyway I think I came up with something nice, and it performs quite well. You can download the source and a bunch of demo’s here Reflection Demos (105).

Here is a list of features:

  • simple setup by default. In most cases doing new ReflectionManager (sourceClip) will suffice
  • default setup is a clip that fades from 40 to 0 alpha at 40% of the image
  • you can change the falloff height, overall alpha, and the redraw interval (eg to mirror video)
  • retrievable reflection and source clips to apply filters or otherwise control clips
  • redraw interval is disconnected from framerate, specify a low redraw interval to save system resources
  • works with scaled, non top left regpoints, and masked clip, using an autobounds detection algorithm
  • works with negative scaled clips
  • tries to warn you in most cases when the result is likely to be different from what you expect
  • very high performance
  • no dependencies on non flash classes

A couple of screenshots of the other demo’s:
Difference process

Using Flash CS 4 Components in FlashDevelop

Friday, August 21st, 2009

While looking for a way to use Flash CS 4 Components in FlashDevelop without creating an intermediate swc, I found that using the separate swc components in the C:\Program Files\Adobe\Adobe Flash CS4\Common\Configuration\Components\User Interface folder didn’t work.

Instead I opened up the User Interface.fla in C:\Program Files\Adobe\Adobe Flash CS4\Common\Configuration\Components, exported this file to an swc and included it in FlashDevelop.

Voila! Looking good so far!

Faking _global in ActionScript 3

Thursday, May 7th, 2009

In ActionScript 2, we had a _global object. Although this opened a world of gruelsome possibilities, it had it’s uses as well. For example it allowed to create reflection mechanism by traversing the package tree and unobtrusive logging by attaching your logger to the _global.log hook.

This prevented you from having to import your logger everywhere and allowed you to easily switch to other loggers, or disable the current one.

Although I do not find many uses for a _global object, this logging feature is one of them, and I expect that for some developers, the ability to store properties all over the place is a nice-to-have as well, although I strongly advise against that:).

In addition, when you are using traces, your traces will not show up in the release player. If you are using FlashDevelop like me, you can redirect to traces to FlashConnect however.

A simple trick you can employ is something like this:

package
{
import org.flashdevelop.utils.FlashConnect;

public class _global_com_yourdomain
{
public static var storage:Object = new Object();

public static function log(…arguments):void
{
FlashConnect.trace (arguments);
}

}

}

Enjoy the abuse :)

You can log, without having to import any classes, and change the logging functionality on the fly whenever you wish! Although you can shorten _global_com_yourdomain to _global, it might be wiser not to, or use _domain instead, to avoid name collisions with others who employ this trick.

I would like to encourage you to look into the Actionscript 3 logging API (Flex) as well though and a tool like the DeMonsters debugger or Arthropod.

Injection Swf Class hook

Saturday, May 2nd, 2009

Also known as:

  • keeping your sources out of the injection swf
  • decoupling your main class from your injection swf

If you are developing your actionscript 2 apps in FlashDevelop, in a lot of cases this means you are using an injection swf.

This injection swf contains all your assets. There are two options to start your program once it’s loaded:

  • tell MTASC to execute your main class once all classes are initialized
  • call your main class method from the swf once everything is loaded

Note that these two points might not be the same. I use a simple fla template which contains a preloader etc, and has its classes exported at frame 20 and its main application function called at frame 40. Although you might argue that an external preloader should have been used and the main fla should only have been 1 frame, that offers new problems, and anyway that is not what this post is about.

Telling MTASC to execute the main class once all classes are initialized will cause initialization to occur at frame 20, using a call on frame 40 of the timeline will cause the application to be initialized at… yes frame 40.

Another difference is that using the MTASC main class option, causes your class file to be excluded during compilation of the injection swf (which is good), using a class hook causes them to be compiled in the injection swf (which is bad).

When the classes of your application are already compiled in the injection SWF, you will run into problems when refactoring the classes, and forget to recompile the injection swf. If you use the MTASC keep flag, all your classes will be removed, which is probably not what you want if you are using v2 components in the SWF.

So the simplest option is not to use:
com.mydomain.client.MainApplication.main (this);

But to use:
_global.com.mydomain.client.MainApplication.main (this);

When you tell FlashDevelop to include your main class, the class will be injected in the injection swf during compilation, so _global.com.mydomain.client.MainApplication.main (this); will call an existing method and your swf will run just fine. On the other hand _global.com.mydomain.client.MainApplication.main (this); will not cause any application classes to be included in your injection swf during export, which is good too.

So almost there, the only thing that’s not so good about this is that the injection swf still has knowledge about your application’s main class, since it’s right there in the _global.com..etc statement.

To fix that you can replace:

_global.com.mydomain.client.MainApplication.main (this);

with

_global.hook(this);

and include this code in your main class:

private static var _instance:MainClass = null;
public static var _installHookTrigger:Boolean = _installHook();

private static function _installHook():Boolean {
_global.hook = function () {
MainClass.main.apply (MainClass, arguments);
}
return true;
}

public static function main (pParent:MovieClip):Void {
_instance = new MainClass(pParent);
}

Just compiling the main class into your swf will cause the _global.hook to be set, and calling it will cause your MainClass’s main function to be called.

Spiffy ain’t it :) ?

Protected: Acoustic Doompriests

Monday, April 20th, 2009

This post is password protected. To view it please enter your password below:


Include code in wordpress posts, the easy way

Saturday, April 11th, 2009

Although there are different plugins out there to help you display your code, there is a very simple solution as well. It does not provide code colouring, linenumbers and all that, but it does create a nice readable non-overflowing area to display your code.

Simply put this in your style.css:

div.codewrapper {
border: 1px solid #DDD;
max-height:200px;
overflow:auto;
width:450px;
height: expression(this.scrollHeight > 200 ? “200px” : “auto”);
white-space:pre;
line-height: 100%;
font-family: Verdana, Arial, Sans-Serif;
font-size:10px;

}

Now if you create a div with class codewrapper, it will look like this:

Although there are different plugins out there to help you display your code, there is a very simple solution as well. It does not provide code colouring, linenumbers and all that, but it does create a nice readable non-overflowing area to display your code.

Simply put this in your style.css:

div.codewrapper {
border: 1px solid #DDD;
max-height:200px;
overflow:auto;
width:450px;
height: expression(this.scrollHeight > 200 ? “200px” : “auto”);
white-space:pre;
line-height: 100%;
font-family: Verdana, Arial, Sans-Serif;
font-size:10px;

}

arguments.caller.name in ActionScript 3

Friday, April 10th, 2009

I was looking for a way to trace the name of the current function or the calling function like it was so simple to do in ActionScript 2 with my reflection package. In ActionScript 3 it’s not so simple.

In ActionScript 3 we use the same approach as Java 10 years ago, throw an exception and parse the stacktrace. Although this will only work in the debug player, however I wouldn’t use this in production code anyway.

package
{

public class DebugUtil
{

public static function getCallingInfo(pInfo:String = “”, pFull:Boolean = false):String {
return getInfo (pInfo, pFull, 2);
}

public static function traceCallingInfo(pInfo:String = “”, pFull:Boolean = false):void {
trace (getCallingInfo (pInfo, pFull));
}

public static function getCallerInfo(pInfo:String = “”, pFull:Boolean = false):String {
return getInfo(pInfo, pFull, 3)
}

public static function traceCallerInfo(pInfo:String = “”, pFull:Boolean = false):void {
trace (getCallerInfo (pInfo, pFull));
}

private static function getInfo (pInfo:String = “”, pFull:Boolean = false, pIndex:Number = 0):String {
CONFIG::EXTENDED_INFO_ON {
try {
throw new Error();
} catch (e:Error) {
var lTrace:String = e.getStackTrace().split(“\tat “)[pIndex+1];
lTrace = pFull?lTrace:lTrace.split(“[")[0];
return (lTrace + “->” + pInfo);
}
}
return pInfo;
}
}

}

Usage:
- define a compiler directive and set it to true or false (can be optimized)

Example:

public class Test extends Sprite
{

public function Test():void
{
init();
}

private function init():void
{
trace (DebugUtil.getCallerInfo(“here”, true));
trace (DebugUtil.getCallingInfo(“here”, true));
}

}

Prints:

Test()[D:\MY_DATA\checkouts\co_as3_library\\src\Test.as:21]->here
Test/init()[D:\MY_DATA\checkouts\co_as3_library\src\Test.as:42]->here

If you use DebugUtil.getCallingInfo(“here”, false) the source line is omited.

I’m not sure what happens in other languages, you might need to replace \tat with \t

Note 1: to use this in FlashDevelop goto Project->Properties->Compiler Options->Additional Compiler Options:
and add -define=CONFIG::EXTENDED_INFO_ON,true

Note 2: in the Flash IDE, goto publish settings->actionscript settings->Config Constants and enter CONFIG::EXTENDED_INFO_ON

In addition you can omit traces in the IDE, but you can’t in FlashDevelop

Grabbing bitmap data from external swf in ActionScript 2

Sunday, March 8th, 2009

Also known as:

  • alternative localization method
  • grabbing bitmap data from a loaded swf in actionscript 2
  • linkageExportForAS in JSFL not working for bitmaps

For Heineken, one of TriMM’s clients, I had to work on a project called the photomodule. Originally written by Paul de Jong, it required some adaptions for another site. One of the adaptions was that the module had to be running in different languages, Portugese, English & Thai (and maybe even more I don’t know).

You can watch it here by the way. Note that all the texts are localized.

Since there was little time to complete the project, I didn’t want to get involved in playing with thai fonts and embedding the right glyphs. Originally the solution was to include every screen twice, once in English and once in Thai. However that wasn’t really going to work as well, since I needed it for 2 or 3 other languages, and I wanted to simplify/refactor the setup in order to get acqainted with it.

So I came up with an idea: I would create a large jpg with all the button skins in it, and just load that skin. Then in Flash I’d have a couple components cutting the bitmap data out of the jpg. Well it turned out that most of the buttons were already available as separate images, and creating a large skin jpg was only going to be more work.

So: external swf, lots of images in it with correct identifier. Brilliant, only there is no way to get to that data except from within that swf. Since in order to get the bitmap data, I have to pass a linkage id, and that won’t work outside the swf.

However before I tell you how to cross that bridge, I hate doing things that can be automated. For example, right clicking 30 button images, and enabling ‘export for actionscript’ and ‘export in first frame’, which is the first step required if we ever want to be able to get to this data dynamically. So you think: well I’ll be damned, I’ve got JSFL up my sleeve. AHAHAHAHA! Gotcha! Macromedia/Adobe has another bug up their sleeve! Which is that you cannot change these properties for a bitmap through JSFL.

So first step is to write a script that wraps all the bitmaps in a movieclip, and enables ‘export for actionscript’ and ‘export in first frame’ for those clips. First problem solved. Now the trick to get to the bitmap data is to create a clip within the swf that contains the images and attach a helper class to it, for example BitmapLoaderHelper.

This class contains the following:

class BitmapLoaderHelper extends MovieClip {

public function loadBitmap (linkageID:String):BitmapData {
var tmp:MovieClip = attachMovie (linkageID, “tmp”, 0);
var bmp:BitmapData = new BitmapData (tmp._width, tmp._height, true);
//draw the image
bmp.draw (tmp, new Matrix(), null, “normal”);
//copy the alpha channel
bmp.draw (tmp, new Matrix(), null, “alpha”);
tmp.removeMovieClip();
return bmp;
}
}

So from your main swf, the process for getting to the BitmapData becomes very simple:

  • load the appropriate skin swf for a given language code containing your bitmaps with predetermined id’s (eg ’select_button’)
  • after loading, attach the BitmapLoaderHelper clip from that swf, to its own timeline and maintain a reference to it
  • when needed retrieve bitmapdata from the swf through the helper
  • In our case we wrapped this whole thing up in a SkinFactory and SkinnedButtonComponents, which included automatic image retrieval for rollovers etc.

    And here is the JSFL I used:

    var dom = fl.getDocumentDOM();
    var lib = dom.library;
    var items = lib.items;
    var item;
    var newSel = [];

    for (var i=0; i<items.length; i++) {
    item = items[i];
    if (item.itemType == “movie clip”) {
    fl.trace (“deleting “+item.name);
    lib.deleteItem (item.name);
    }
    }

    for (var i=0; i<items.length; i++) {
    item = items[i];
    if (item.itemType == “bitmap”) {

    fl.trace (“Processing “+item.name);
    item.compressionType = “lossless”;
    item.allowSmoothing = true;

    var newName = item.name.substring (0, item.name.indexOf(“.”));
    fl.trace (“Creating wrapper clip with name:”+newName);

    lib.addNewItem( “movie clip”, newName);
    lib.editItem( newName );

    var tl = dom.getTimeline();
    tl.layers[0].name = “Wrapped Bitmap”;
    lib.addItemToDocument( {x:0, y:0}, item.name );

    newSel[0] = tl.layers[ 0 ].frames[ 0 ].elements[ 0 ];
    dom.selectNone();
    dom.selection = newSel;
    var mat = dom.selection[0].matrix;
    mat.tx = 0;
    mat.ty = 0;
    dom.selection[0].matrix = mat;
    dom.selectNone();
    dom.exitEditMode();

    lib.selectItem (newName, true);
    lib.setItemProperty( “linkageExportForAS”, true);
    lib.setItemProperty( “linkageExportInFirstFrame”, true);
    }
    }

    lib.addNewItem (“movie clip”, “BitmapLoaderHelper”);
    lib.selectItem (“BitmapLoaderHelper”, true);
    lib.setItemProperty( “linkageExportForAS”, true);
    lib.setItemProperty( “linkageExportInFirstFrame”, true);
    lib.setItemProperty( “linkageClassName”, “!replacethiswithyourpackage!.BitmapLoaderHelper”);

    The _lockroot of all evil!

    Thursday, March 5th, 2009

    Also known as: losing your _root reference during asynchronous calls.

    I was browsing through my drafts today, since I haven’t written anything in god knows how long, and I happily started deleting everything not having anything todo with AS3, since I finally moved on. But then I ran into some posts that I thought are still worth writing about, so I’ll try to post something every couple of days for the next couple weeks, to get rid of that backlog.

    For today, the _lockroot of all evil!

    If you don’t know what _lockroot is, stop reading now!

    Really you should stop reading now…

    I’m sure we’ve all heard (all us actionscript programmers that is), that you shouldn’t rely on _lockroot. I’m sure most of us have violated that rule too one time or another, until we finally found a framework that solves it (but that’s another story).

    So why shouldn’t we use _lockroot?

    Well there are a couple of things I’d like to share. I think that using _lockroot from movieclip classes, although it might not be a good thing, is not necessarily problematic, at least I haven’t run into any bugs doing that, but maybe you have.

    The real problem is that _lockroot seems to make it easy to access the _root for your subapplication even from non movieclip classes. Although this may seem to work correct, I’ve noticed on several occasions that _root in that case does not point to the _root of your swf, but to the _root of the swf that loaded the class you are referencing _root from (still with me?).

    Another subtle bug which I have encountered twice, with no way to reproduce in a cleanroom setting, is that _root resets itself from the subswf root to the parent root during an asynchronous to for example a webservice.

    For example:

    trace (_root); //_level0.mysubswf
    //do webservice call here and execute onResult

    onResult () {
    trace (_root); //traces _level0
    }

    So conclusion: if you do use _lockroot, do not use it from non movieclip classes.

    Any solutions?

    Well if we stay in the realm of easy hacking, you might want to create a global table storing your roots under an identifier. If you want a more solid approach, in our framework, each application and subapplication extends Application, which has a getTimeline() method.
    The applications are registered in an ApplicationRegistry, and you can retrieve their instances by passing in a class reference. So to retrieve the root for my sub application I might do:

    Application (Application.getRootApplication().getRegistree(com.objectpainters.SubApplication)).getTimeline();

    I have never needed to yet though, and if I had I’d probably wrap it, cache it or whatever.

    So play with _lockroot in as2 all you want, but keep this possibility of hard to track, incredibly nasty bugs in the back of your head.

    ActionScript 2 Alert with html formatting

    Wednesday, March 4th, 2009

    To format the text of an Alert component in html, do this:

    var lNewContentAlert:Alert = Alert.show (html here, …otherparams here);

    //turn on html for the alert’s textarea
    var lAlertTextArea:TextArea = lNewContentAlert.content.text_mc;
    lAlertTextArea.html = true;