Archive for the ‘JSFL’ Category

Batch Compiles and Makefiles With JSFL

You may sometimes find yourself compiling projects made of multiple flas that each inherit from the same Document Class. But what happens when you have to modify the Document Class in the middle of the project? All the inheriting flas must themselves be re-compiled. Let’s reflect for a moment on the implications here:

  • Two flas : That’s manageable. I can handle that.
  • Three flas : This is starting to get a little irritating…
  • Five flas : This is a complete waste of time!
  • Ten flas : !!!
  • Twenty flas : …
  • Fifty flas : ???

Wouldn’t it be nice to just click a single button and compile everything at once?

Meet JSFL.

// File named "batchCompile.jsfl"
//    USAGE : Simply double-click the file icon in your explorer window.
//                If you have the Flash IDE, it will run this script as a command.
 
fl.trace("Batch Publish");
var proceed = true;
 
// Enviornment variables.///////////////////////////
////////////////////////////////////////////////////
 
// the drive on which the project lives.
var drive = "file:///c|/";
 
// user's windows environment.
// Replace "MY_USERNAME" with your username
var user = "MY_USERNAME/";
 
// path from windows enviornment to the flas.
var projectLocation = "My Documents/MY_SOURCE_FILES/";
 
 
 
// log file...
var logURI = "";
var errorsURI = "";
 
//////////////////////////////////////////////////
//////////////////////////////////////////////////
 
if(proceed){
 
	var success = true;
 
	// eg : path == "Documents and Settings/theHorseman/My Documents/scriptocalypse/source"	
	var path = "Documents and Settings/" + user  + projectLocation;
 
 
	var files = [
					"Main.fla",
					"Asset0.fla",
					"Asset1.fla",					
					"Asset2.fla",					
					"Asset3.fla",					
					"Asset4.fla",					
					"Asset5.fla"
				];
	fl.trace("Proceeding");
	var i = 0;
	var ilen = files.length;
 
	var successLog = "";
 
	// external logs...
	logURI = drive+path+"batchPublishLog.txt";
	errorsURI = drive+path+"errors.txt";
 
	createLog();
	createErrorCheck();
	//////////////////
 
	for(i = 0 ; i < ilen ; i++){
		var fileURI;
		var exists;
 
		exists = FLfile.exists(drive+path);
		if(!exists){
			alert("Failed to find "+drive+path);
			success = false;
			break;
		}
 
 
 
 
		fileURI = drive+path+files[i];
		exists = FLfile.exists(fileURI);
		var DOM;
		var publishSuccess;
		fl.trace(files[i]+" exists : "+exists+"\n");
		if(exists){
			fl.openDocument(fileURI);
			DOM = fl.getDocumentDOM();
			publishSuccess = publish(DOM, logURI);
 
			if(!publishSuccess){
				alert("Failed to publish "+files[i]+"!");
				fl.trace("Failed to publish "+files[i]+"!\n  Checking the errors.txt log for more details...\n\n"+FLfile.read(errorsURI)+"\n-------------------------------------------------------------------\n");
				success = false;
				break;
			}
			successLog += ("published : "+files[i]+"\n");
			//DOM.close();
 
		}else{
			alert("Failed to open "+files[i]+"!");
			fl.trace("The file '"+fileURI+"' does not exist!\n");
			success = false;
			break;
		}
 
	}
 
	if(success){
		fl.trace("----------------------\n------ Results -------\n----------------------\n");
		fl.trace(successLog);		
		fl.trace("-------------------------\n--- Publish Succeeded ---\n-------------------------");
		alert("Batch Publish Succeeded!");
	}else{
		fl.trace("----------------------\n------ Results -------\n----------------------\n");
		fl.trace(successLog);
		fl.trace("FAILED AT : "+files[i]+"!");
		fl.trace("\n----------------------\n--- PUBLISH FAILED ---\n----------------------");
		alert("BATCH PUBLISH FAILED!");
	}
}
 
function publish(DOM, logURI){
	var success = true;
	if(DOM){
		DOM.publish();
		log(DOM.docClass+" results :\n\t");
		fl.outputPanel.save(logURI,true);
		fl.compilerErrors.save(logURI,true);
		logCompileErrors();
		log("\n");
	}else{
		success = false;
	}
 
	// found any compile errors?
	if(FLfile.read(errorsURI) != ""){		
		success = false;
	}
 
	return success;
}
 
function createErrorCheck(){
	FLfile.write(errorsURI, "");
}
function logCompileErrors(){
	fl.compilerErrors.save(errorsURI);
}
 
function createLog(){
	FLfile.write(logURI, "Compile Log...\n");
}
 
function log(message){
	FLfile.write(logURI, message, "append");
}

Using this JSFL script, I specify a project folder containing my flas, and simply tell the Flash authoring tool to open them, then publish them. (I decided not to close them after I’m done so I commented out the “DOM.close();” command, but you can uncomment that if your project is very large and you’d rather not leave multiple flas open in the editor at once). Because I wanted to waste as little time as possible, I tell the build script to halt execution if the compiled swf generated a compiler error. The batch compile will only run to completion if all the assets compile successfully.

So, what in the world is this JSFL thing anyway?

You probably know that ActionScript is the language by which you can cause a .swf file to perform feats of magic and wonderment at runtime. JSFL is the language by which you can cause the Flash IDE, and your fla document to perform feats of magic at authoring time. Using it, you can do all manner of amazing things like automate the naming of library symbols, automate the creation of fla templates, and as above, automate compilation of large projects.

You might be saying to yourself “Huh, this JSFL stuff looks a lot like JavaScript.” That’s because it kind of is JavaScript. It’s a little bit of a shock to go back to loosely typed data and prototype inheritance, but it’s worth the effort when it can save you so much time in the end.

You might also be looking at the above code snippet and thinking to yourself “You know, why are those path names hard-coded into the build script? I want them to be in an external config file!” The good news is that you absolutely can do that! You’ll notice in the script I’ve written that I make use of the Flash IDE’s ability to read, write, and create files on the hard drive in order to verify the existence of the flas, and to write error logs. Those same functions can be used to read a config file wherein you keep your own local drive information and file lists. The only reason I have not done so in this file is a lack of time to refine the script.

Tags: , ,

9 Comments