Latest in Articles

Working With Silverlight: My Impressions

ActiveX Problems with Flash

Beyond the Valley of Flash - Part 1

Beyond the Valley of Flash - Part 2

Using Ant with Flash

More pages in Articles...

 

Beyond the Valley of Flash - Part 2


Intermediate Ant, Mtasc, and MX2004.
2005-07-28

This article continues onward from Beyond the Valley of Flash- Part 1.

Compiling Caveats

Although Mtasc is very cool, attempting to migrate a large project over from MX2004 isn't seamless. Although I have moved a smaller project over, those with lots of code will find that Mtasc is slightly stricter with its code creation.

Class Space vs. Clip Space

You may notice that there is no timeline that MainClass exists in. Although the main() function is called in the _root timeline, you must explicitly use _root in your code. The code is actually all kept and executed within the class not the timeline. We're calling the main() function in _root's first frame but this does not mean that our code exists within a movie clip. Main is a static function, so it is part of the class, not any clip.

This is an important distinction when it comes to the life cycle of a flash variable. If a variable is not referenced by any other variable within the flash movie, then its considered 'dead' and thrown out. This is very vaguely what garbage collection is about.

When we compile from within MX2004, our variables are generally inserted into a movie clip at some point. And as long as that clip exists, then our variables will exist, as a general rule. But in Mtasc, all our variables aren't necessarily referenced by movie clips, they're all within our class. To keep flash from garbage collecting our class variables its best to create a static instance of our class within our class:

private static var mainClass:MainClass;

And our main() function:

 public static function main(){
         mainClass = new MainClass();
         }

This creates a static copy of our class, which assures us that flash will not delete the mainClass variable once the main() function is finished executing.

More on ClassSpace

Notice this MainClass line in particular:

pic = new Picture( clip, tmp.pic , tmp.text ,this);

You might think you could do:

new Picture( clip, tmp.pic , tmp.text ,this);

But no, this won't work. Mtasc needs to assign it to something.

You might think you could do:

var pic = new Picture( clip, tmp.pic , tmp.text ,this);

But no, because flash will remove all local variables after they are used. You must use a form such as:

pic = new Picture( clip, tmp.pic , tmp.text ,this);

To make sure that the variable isn't deleted after the function finishes.

Compilation Flags

When compiling files for mtasc, the command line options are important to pay attention to. Since we're using Ant to compile, our options look like this:

		<exec executable="${mtasc}" failonerror="true">
<arg value="-cp"/>
<arg value="${MyClassPath}"/>
<arg value="-swf"/>
<arg value="${inFile}"/>
<arg value="-out"/>
<arg value="${outFile}"/>
<arg value="-main"/>
<!-- <arg value="-v"/> -->
<arg value="${mainclass}"/>
</exec>

Since we're creating an output swf (-out) based on an input swf (-swf) we must not use the -header flag.

Warning about using the -mx flag and mx.utils.Delegate

The -mx flag is stated on mtasc.org as 'use precompiled MX classes'. The -mx usage info also has a lot of references to mx 'components' making me think that 'precompiled MX classes' == 'swc components'. After all, swc components are just precompiled MX classes and movie clips. BUT what the -mx flag does is it simply leaves any already-compiled classes who's root package is 'mx' intact. If the class exists in your input swf, it will be left untouched and put into the output swf. So it not only uses the precompiled mx component files but all mx classes.

The most common issue this causes is with mx.utils.Delegate. If you create code that depends on mx.utils.Delegate in your classes, and you use the -mx flag, mx.utils.Delegate will not be added to your swf because its part of the 'mx' package. You'll need to add the class to your input swf by adding this or similar code to your MX2004 .fla:

var foo = mx.utils.Delegate;

This will insert the class into your swf, so that it will be available to Mtasc. Your best bet tho, if you are not already dependent upon mx.utils.Delegate, is to use a similar class, such as Proxy by Joey Lott.

MX2004 Actionscript and Mtasc: Adding classes and packages.

If you have classes that are included within MX2004, but not linked to from inside your main() insertion point, they will disappear from your swf. You will need to explicitly tell Mtasc to add these files.

In order to add classes to your file explicitly you'll need to use the -pack flag, or simply type the name of the class.

To add a package:

<arg value="-pack"/>
<arg value="my/package"/>

To add a single class:

<arg value="my/package/MyClass"/>

Note that Mtasc will look for these files in the specified classpaths.

I find mixing MX2004 classes and Mtasc classes to be a bad way of coding. You should generally either code completely in Mtasc, or MX2004. Mixing the two is a headache to compile, although neither are incompatible with each other, so its perfectly acceptable if required.

Mtasc and the MX2004 Library

If you export library symbols in MX2004 that are linked to classes, Mtasc will issue a warning that these classes need to be explicitly compiled into your swf. Example: I've created a symbol called 'RegisterUserGui' which is linked to the class my.packages.gui.RegisterUserClass. I export the swf from MX2004, for use with Mtasc. Unless RegisterUserClass is already included elsewhere within my main() insertion point, Mtasc will come up with the error:

 [exec] Warning : The MovieClip clip needs the class my.packages.gui.RegisterUserClass 
	  		which was not compiled :
         [exec] Please force compilation of this class by adding it to the commandline.

Now there are two ways to add this class to the swf, by adding it to the ant build:

<arg value="my/packages/gui/registerUserClass"/>

or by using Object.registerClass() somewhere within your insertion point. Putting this in your MainClass works well:

registerClass("RegisterUserGui",my.packages.gui.RegisterUserClass);

Note that you must call registerClass() before you call attachMovie() for this to work.

I'm torn as to which method is better, but I'm going to go with the registerClass() method because it is tied to the code instead of the build.

Mtasc vs MX2004

And so in closing, how useful is Mtasc in your everyday routine? Is being able to compile flash faster worth it? Why jump through these extra hoops when MX2004 does a good job already?

If you're a single person team, working on small projects on Windows/Mac, then forget it, Mtasc probably won't give you a noticable speed increase, and you've already got the tools.

If you work on a small team, say as a coder and developer pair, then the advantage is simple. You can code, they can design, and both work on the same files! The designer can put assets in the fla, while you can attach your code in the swf.

And if you work on a larger team, with lots of code, then of course you'll benefit from faster compile times. By standardizing on Ant to build, and using Mtasc to compile, you'll see blazing-fast compile times.

And last but not least, this is a setup that makes open source geeks happy. You can build useful stuff with free tools, and even potentially work on *nix systems. While we wait for MX2004 to get across to *nix systems, or wine to fix the installer issues (and my sources say this won't happen anytime soon), this setup is a very welcome edition to *nix geeks.

Happy Coding!

 
 

©2004 Chris Hill. All Rights Reserved.Legal Crapola