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!
|