bootanimation viewer
reference:
http://www.droidforums.net/forum/droid-hacks/33932-bootanimation-zip-file-explained.html
/**
* Copyright wh0 ( http://wonderfl.net/user/wh0 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/nE7v
*/
package {
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.*;
import nochump.util.zip.*;
public class FlashTest extends Sprite {
private static const ffa:Array = [new FileFilter("Compressed (zipped) Folder (*.zip)", "*.zip")];
private static const tfo:TextFormat = new TextFormat("Small Fonts", 8, 0x666666);
private static const re:RegExp = /^(.+)\/.+\.png$/;
private var fr:FileReference;
private var tf:TextField;
private var w:Number;
private var h:Number;
private var fps:Number;
private var ox:Number;
private var oy:Number;
private var parts:Array;
private var partMap:Object;
private var loadersRemaining:int;
private var nextPart:int;
private var loopCount:int;
private var nextFrame:int;
private var img:Loader;
public function FlashTest() {
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, error);
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
tf = new TextField();
tf.mouseEnabled = false;
tf.defaultTextFormat = tfo;
tf.text = 'click';
tf.width = tf.textWidth + 4;
tf.height = tf.textHeight + 4;
tf.x = (stage.stageWidth - tf.width) >> 1;
tf.y = (stage.stageHeight - tf.height) >> 1;
addChild(tf);
fr = new FileReference();
stage.addEventListener(MouseEvent.CLICK, click);
fr.addEventListener(Event.SELECT, select);
fr.addEventListener(Event.COMPLETE, zipComplete);
}
private function error(e:UncaughtErrorEvent):void {
var tf:TextField = new TextField();
tf.defaultTextFormat = tfo;
tf.width = stage.stageWidth;
tf.height = stage.stageHeight;
tf.text = String(e.error);
addChild(tf);
}
private function click(e:MouseEvent):void {
fr.browse(ffa);
}
private function select(e:Event):void {
fr.load();
}
private function zipComplete(e:Event):void {
removeChild(tf);
stage.removeEventListener(MouseEvent.CLICK, click);
var zf:ZipFile = new ZipFile(fr.data);
// read desc.txt
var ze:ZipEntry = zf.getEntry('desc.txt');
var ba:ByteArray = zf.getInput(ze);
var desc:String = ba.readUTFBytes(ba.length)
var lines:Array = desc.split('\r\n');
// first line: <width> <height> <fps>
var header:Array = lines.shift().split(' ');
w = parseInt(header[0], 10);
h = parseInt(header[1], 10);
fps = parseInt(header[2], 10);
// precompute image origin
ox = (stage.stageWidth - w) >> 1;
oy = (stage.stageHeight - h) >> 1;
// read animation parts
parts = [];
partMap = {};
for each (var line:String in lines) createPart(line);
// read frames
for each (ze in zf.entries.sortOn('name')) createFrame(zf, ze);
Wonderfl.log(loadersRemaining);
}
private function createPart(line:String):void {
// skip blank lines...
if (!line) return;
// part line: p <loops> <pause> <name>
var tokens:Array = line.split(' ');
if (tokens[0] != 'p') return;
var part:Part = new Part();
part.loops = parseInt(tokens[1], 10);
part.pause = parseInt(tokens[2], 10);
part.name = tokens[3];
parts.push(part);
partMap[part.name] = part;
}
private function createFrame(zf:ZipFile, ze:ZipEntry):void {
var m:Object = re.exec(ze.name);
if (!m) return;
loadersRemaining++;
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, pngComplete);
l.loadBytes(zf.getInput(ze));
partMap[m[1]].frames.push(l);
}
private function pngComplete(e:Event):void {
e.target.content.width = w;
e.target.content.height = h;
e.target.content.x = ox;
e.target.content.y = oy;
if (!--loadersRemaining) start();
}
private function start():void {
stage.frameRate = fps;
nextPart = 0;
loopCount = 0;
nextFrame = 0;
addEventListener(Event.ENTER_FRAME, frame);
}
private function frame(e:Event):void {
if (img) removeChild(img);
img = parts[nextPart].frames[nextFrame];
addChild(img);
if (++nextFrame >= parts[nextPart].frames.length) {
nextFrame = 0;
if (parts[nextPart].loops && ++loopCount >= parts[nextPart].loops) {
loopCount = 0;
if (++nextPart >= parts.length) {
throw 'end of animation';
removeEventListener(Event.ENTER_FRAME, frame);
}
}
}
}
}
}
internal class Part {
public var loops:int;
public var pause:int;
public var name:String;
public var frames:Array = [];
}