haXe

Using haXe with Flash9

You can use the haXe language to build Flash9 SWF. To do that, simply compile using -swf-version 9 and the haXe compiler will generate a Flash Player 9 compatible SWF.

Example :

class Test {
    static function main() {
         // creates a TextField         
         var tf = new flash.text.TextField();
         tf.text = "Hello World !";
         // add it to the display list
         flash.Lib.current.addChild(tf);
    }
}

Compile using the following HXML file :

-swf test.swf
-swf-version 9
-main Test

When you compile a project for Flash9, you will have to use the new ActionScript3/Flash9 API instead of the old ActionScript2/Flash8 ones. You can find these described in the haXe API (click on flash9 to unroll the menu). These API are exactly the same that are available from AS3 and they contain additional undocumented methods.

These API are documented on the Adobe livedocs

Although there might be some bugs left, the haXe Flash9 code generator is working correctly and in some cases generate faster code than the official Flex compiler. Try it yourself and report your findings on the haxe mailing list.

You can add debug informations to your Flash9 swf by compiling with -debug. This will enable you to see haxe sources file and line numbers when a runtime exception occur.

Using the Library

If you having graphical resources that were created by Flash IDE (either MX 2004 or CS3) or SwfMill, you can use them from your Flash9 code by doing the following :

  • with Flash MX / SwfMill : use an Identifier (linkage name) for your resource, as you would do normally for an attachMovie
  • with Flash CS3 : use a AS3 class name as your would do normally for AS3
  • statically link your library in your output SWF by using -swf-lib

Attaching By-Name

haXe will automatically creates a Flash9 class for MovieClips that have a linkage name, if there's not already one available. You can then directly use flash.Lib.attach("myname") that will create an instance of this movieclip. For example :

class Test {
   static function main() {
         var s = flash.Lib.attach("Shape");
         flash.Lib.current.addChild(s);
   }
}

This assumes that you have a clip with either a linkage or a class name "Shape".
In the case one of your graphics as a linkage identifier but no class is defined, you can catch the exception thrown by flash.Lib.attach or using the Flash9 Debug Player.

Class binding

If OTOH you want to redefine/extend the behavior of the MovieClip, then you can simply define a class in haXe with the same name, using the extern keyword :

// Test.hx
extern class Shape extends flash.display.MovieClip {
   public function move() { x += 2; y += 2; }
}

class Test {
    static function main() {
         var s = new Shape();
         flash.Lib.current.addChild(s);
         s.move();
    }
}

Compile it using the following HXML :

-swf test.swf
-swf-version 9
-swf-lib lib.swf
-main Test

This will create a SWF that will, once opened, display the graphics named Shape and move it a little bit. In the case one of your graphics as a linkage identifier but no class is defined, the Flash Debug Player 9 should give you an error when loading it.

Embedding a font

If you want to embed a font, make a resource.xml file like this:

<?xml version="1.0" encoding="iso-8859-1" ?>
<movie version="9">
    <background color="#555555"/>
    <frame>
    <library>
        <font name="Symbols" import="font/dejavusans.ttf" 
glyphs="&#x2605;&#x2606;&#x2613;&#x2620;&#x2713;&#x2714;&#x2715;&#x2716;&#x2717;&#x2718;&#x2764;"/>
    </library>
    </frame>
</movie>

Use swfmill simple resource.xml resource.swf to build resource.swf with the font. Add the following somewhere:

class Symbols extends flash.text.Font {}

Next, use -swf-lib resource.swf to link resource.swf into the final .swf, and use your font using the name Symbols. Be sure to set embedFonts = true.

Redefining Methods

In haXe, you often bind events by redefining some method of an object :

class Button {
    public function new() {
        //....
    }
    public function onClick() {
    }
}

class Application {
    static function main() {
         var b = new Button();
         b.onClick = function() { trace("Button clicked !"); };
    }
}

This is working very nicely in haXe since functions types are infered, it means there is not a single Function type and that when assigning functions together, the haXe strict typing ensure you that you will not mistake the parameters types or the return result.

However, in Flash9, redefining methods is not possible and will lead to a runtime error Can't redefine method xxxx. To deal with this, you need to add the keyword f9dynamic before the function declaration :

    public f9dynamic function onClick() {
    }

The f9dynamic keyword is supported on all plaforms but has only an effect when compiling to Flash9. Its effect is to turn the function into a variable, as you would have written the following :

class Button {
    public var onClick : Void -> Void;
    public function new() {
        onClick = function() { };
    }
}

The only consequence of using f9dynamic is that you cannot call super.onClick() when extending the class Button. Please notice also that the method is defined in the instance properties and not is not part of the class prototype. This might take a very small amount of additional memory.

Incompatibilities

Some specific features will fail to compile or run on Flash9 :

  • overriding instance methods not defined with f9dynamic (see up)
  • having a try/catch block inside an expression, such as the following sample :
    var x = try f() catch( e : Dynamic ) null;
  • having a class implementing another class (accepted in haXe but not in Flash9)
  • having a class implementing Dynamic (accepted in haXe but not in Flash9)
  • there is no equivalent of Flash Error class in haxe, you can throw any object so you don't need to inherit from Error. It is a good practice in AS 3 to throw objects of classes that inherit the Error class but it is not mandatory.
  • there are some issues with nullness of Int, UInt, Float and Bool (see below)

Everything else should work perfectly and provide the same result on all the supported platforms.

Nullness of Basic types

In Flash9, the basic types Int, Float and Bool can't be assigned or compared with the null value. Int variable default value is 0, Float is NaN and Bool is false.

If you want to be able to store null values in these basic types, please use the types Null<Int> , Null<Float> and Null<Bool> instead. This will work the same as basic types, except that at runtime a Dynamic (Object in AS3) type will be used, enabling the null value to be stored.

For optional arguments, the Null<...> type is automatically used.

Using Null instead of the basic type will degrade performance a bit, but there is no reason to worry unless it's used for speed critical methods (in that case don't use optional arguments or Null types).

This can also have some undesirable side effects. For example the following method will return null when called without arguments.

  function foo( ?x : Int ) : Null<Int> {
      return x;
  }

While the following will return 0 since null is converted to Int when returned :

  function foo( ?x : Int ) : Int {
      return x;
  }

The same problem can occur with Arrays :

   var a = new Array<Int>();
   trace(a[999]); // 0 , since it's Int default value
   var b = new Array<Null<Int>>();
   trace(b[999]); // null : it works this time

As a conclusion, while basic types are really faster, be careful when using them.

version #1075, modified 2008-05-03 00:27:14 by ncannasse