kelvinluck.com

a stroke of luck

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):

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.

/**
* 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] + '">' + newline;
      }
      r += '</classes></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.

8 Comments, Comment or Ping

Reply to “Automatically generating exclude.xml files”