A problem occured while loading the plugin: krl_flickr_photoset -> : Assigning the return value of new by reference is deprecated on line 18
kelvinluck.com: Automatically generating exclude.xml files
Get Firefox! creative commons

Automatically generating exclude.xml files

I’ve recently been working on a project where a number of swf’s use common classes. The initial swf loaded contains most of these classes but so do the child swfs it loads into itself. This is because they need to be able to call methods in and dispatch events to classes in the main swf. Importing the classes gives me compile time type checking and auto complete (in FDT – my editor of choice).

So I discovered excude.xml files. These allow you to specify classes which you don’t want to be compiled into a given swf. Since all AS2 classes live in the _global scope you can share them between different swf’s. So if your initial swf includes a class that you use in a child swf you load into it then compiling that class into the child swf is redundant.

exclude.xml files are easy enough to understand – simply create a file with the same name as your fla but with _exclude.xml added on (e.g. nav.fla would have an exclude file called nav_exclude.xml) and in it list all the classes you want to exclude from compilation into that swf.

The problem with exclude.xml files is when a class you are excluding has a dependency on other classes the dependant classes aren’t automatically excluded. And manually figuring out the dependency tree in any non-trivial application is tricky to say the least. So what we need is a way to find all of the classes which are included in a given swf. You can then use this to generate an exclude list for any other swfs that will be loaded after it.

I found a program which sounded like they might do just that: sexieR on OSFlash. Unfortunately I got put off by it’s requirements and and didn’t get around to finding out if it could do what I wanted.

Then I realised I could generate the exclude list very easily myself from Actionscript! Since all classes are instantiated as Objects in the _global namespace we can simply recursively loop over this namespace and note all the classes we come across. So I wrote my “IncludedClasses” class, which does the above and outputs a string for you to copy and paste into an exclude.xml file. You simply have to temporarily include this line in your “master” fla (the one which contains the classes you want to access from other flas):

ActionScript:
trace(com.kelvinluck.util.IncludedClasses.getInstance().getExcludeXml());

Then in the output window you will find a string which you can copy and paste into an XML file with the correct name and then – bobs your uncle – you’re sorted :)

The IncludedClasses class is shown below or you can download it here.

ActionScript:
/**
* Class: IncludedClasses
*
* @author KLuck
*/

class com.kelvinluck.util.IncludedClasses
{
       
        private static var instance:IncludedClasses;
       
        /**
        * Private constructor - Singleton
        **/

        private function IncludedClasses()
        {
               
        }
       
        function getExcludeXml():String
        {
                var classes:Array = _arrayUnique(_getClasses(_global, '', []));
                var r:String = '<excludeAssets>' + newline;
                for (var i:Number=0; i<classes.length; i++) {
                        r += '<asset name="' + classes[i] + '"></asset>' + newline;
                }
                r += '</excludeAssets>';
                return r;
        }
       
        function getArrayString():String
        {
                var r:String = '["' + newline;
                r += _arrayUnique(_getClasses(_global, '', [])).join('", "');
                r += '"]';
                return r;
        }
       
        private function _getClasses(obj:Object, path:String, classes:Array):Array
        {
                var ret:Array = [];
                for (var name:String in obj) {

                        if (typeof(obj[name]) == 'function') {
                                var firstLetter:String = name.substr(0, 1);
                                if (firstLetter.toUpperCase() == firstLetter) {
                                        classes.push(path + '.' + name);
                                }
                        } else {
                                var passPath = path == '' ? name : path + '.' + name;
                                classes = classes.concat(_getClasses(obj[name], passPath, classes));
                        }
                }
                return classes.concat(ret);
        }
        private function _arrayUnique(a:Array):Array
        {
                var o:Object = {};
                for (var i:Number=0; i<a.length; i++) {
                        o[a[i]] = true;
                }
                var r:Array = [];
                for (var i:String in o) {
                        r.unshift(i);
                }
                return r;
        }
       
       
        /**
        * @return singleton instance of IncludedClasses
        */

        public static function getInstance():IncludedClasses
        {
                if (instance == null)
                        instance = new IncludedClasses();
                return instance;
        }
        function toString():String
        {
                return '[com.kelvinluck.util.IncludedClasses]';
        }
       
}

So simply run this script in your “master” fla (or library fla) and then create exlude files for all your “slave” fla’s. In the project I’m working on this knocked 30-40KB of each of the included swf’s which makes it definitely worthwhile.

  1. hi there,
    well, this seems like some usefull thing. I will take a look and see how it goes, but anyhow, thnxs for sharing!
    goliatone


    goliatone    Jul 30, 11:00    #
  2. YTMND! Sometimes the simplest solutions are the best… I do have one suggestion though, it would be nice to be able to pass class references to the getExcludeXml function so that they would get “excluded” from the “exclude.xml” output. Otherwise, thanks!


    caseyc    Dec 31, 15:53    #
  3. In advertising we are always hitting up against file size restraints. Before this all those bytes would come out of the images. Once I exported a size report, I saw that I was losing 60 odd K on AS that I didn’t need. This is amazing!

    I am an AS3 guy myself, but AS2 is still what most everyone knows so I am stuck working in it. AS3 does this automatically from what I understand.


    Robert Abramski    Apr 8, 20:58    #
  4. Hi Kelvin,
    thanks for your tool. I just want to point out a case where it goes into an infinite loop: If you use the Xray connector in your project, there is a circular reference in the class that your class doesn’t handle.
    take care, and let me know if you get around to fixing it
    Ariel


    ariel    May 29, 07:47    #
  5. Hi Ariel,

    Glad you like the tool :)

    I’m afraid I haven’t done any AS2 for quite a while so I’m unlikely to update the script but if you figure out how to deal with the circular reference let me know and I’ll update the post,

    Cheers,

    Kelvin :)


    Kelvin Luck    May 29, 20:13    #