/**
* Copyright fujista ( http://wonderfl.net/user/fujista )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/3Awm
*/
package {
import com.codeazur.as3swf.*;
import com.codeazur.as3swf.tags.*;
import com.codeazur.as3swf.events.*;
import com.codeazur.as3swf.timeline.*;
import com.bit101.components.*;
import flash.events.*;
import flash.errors.*;
import flash.display.Sprite;
import flash.net.FileReference;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
public class MovieClipTranscoder extends Sprite {
// Compornents
protected var status:TextArea;
protected var browse:PushButton;
protected var filename:Text;
protected var progress:ProgressBar;
protected var file:FileReference;
protected var swf:FJ_SWF;
protected var timeline:FJ_SWFTimeline;
protected var _targets:Dictionary;
protected var _process:Dictionary;
public function MovieClipTranscoder():void {
file = new FileReference();
file.addEventListener(Event.SELECT, onFileSelect);
file.addEventListener(Event.COMPLETE, onFileComplete);
file.addEventListener(IOErrorEvent.IO_ERROR, onFileIOError);
file.addEventListener(ProgressEvent.PROGRESS, onFileProgress);
swf = new FJ_SWF();
swf.addEventListener(SWFEvent.HEADER, onSWFHeader);
swf.addEventListener(SWFEvent.PROGRESS, onSWFProgress);
swf.addEventListener(SWFEvent.COMPLETE, onSWFComplete);
swf.addEventListener(SWFErrorEvent.ERROR, onSWFError);
timeline = swf.timeline as FJ_SWFTimeline;
timeline.addEventListener(SWFMessageEvent.NOTICE, onSWFMessage);
4
_targets = new Dictionary();
_process = new Dictionary();
initComps();
}
protected function initComps():void {
new Label(this, 5, 5, "File:");
browse = new PushButton(this, 360, 25, "Browse", onFileBrowse);
filename = new Text(this, 5, 25, null);
filename.width = 350;
filename.height = 20;
filename.editable = false;
new Label(this, 5, 55, "Progress:");
progress = new ProgressBar(this, 5, 75);
progress.width = 455;
new PushButton(this, 180, 180, "SAVE", onFileSave);
new Label(this, 5, 280, "Information:");
status = new TextArea(this, 5, 300, null);
status.width = 455;
status.height = 160;
status.editable = false;
status.text = "Initialize Completed.";
}
protected function onFileBrowse(e:MouseEvent):void {
file.browse();
}
protected function onFileSave(e:MouseEvent):void {
// file.save(file.data, file.name);
}
protected function onFileSelect(e:Event):void {
progress.maximum = e.target.size;
filename.text = e.target.name;
status.text = "File Loading";
browse.enabled = false;
e.target.load();
}
protected function onFileComplete(e:Event):void {
status.text = status.text + "\nComplete.";
swf.loadBytesAsync(e.target.data);
}
protected function onFileProgress(e:ProgressEvent):void {
progress.value = e.bytesLoaded;
}
protected function onFileIOError(e:IOError):void {
status.text = "File IO Error.\n" + e.toString();
}
protected function onSWFHeader(e:SWFEvent):void {
progress.maximum = e.bytesTotal;
status.text = swf.toString();
}
protected function onSWFProgress(e:SWFEvent):void {
progress.value = e.bytesParsed;
}
protected function onSWFComplete(e:SWFEvent):void {
progress.value = e.bytesParsed;
status.text = "Max Character Id: " + timeline.maxCharacterId + "\n";
parseTimeline(timeline);
for (var id:String in _process) {
status.text += "Process Id: " + id + " / TotalFrame: " + _process[id] + "\n";
}
}
protected function onSWFError(e:SWFErrorEvent):void {
status.text += "\n" + e.toString() + "\n";
}
protected function onSWFMessage(e:SWFMessageEvent):void {
status.text += "\n" + e.toString() + "\n";
}
protected function parseTimeline(tl:SWFTimeline):Boolean {
var hasTarget:Boolean = false;
var frameCount:Dictionary = new Dictionary();
for (var i:uint = 0; i < tl.frames.length; i++) {
var frame:Frame = tl.frames[i];
// フレーム内で定義されたオブジェクト内
for each (var id:uint in frame.characters) {
// MovieClipを抽出
if (timeline.tags[timeline.dictionary[id]] is TagDefineSprite) {
var sprite:TagDefineSprite = timeline.tags[timeline.dictionary[id]] as TagDefineSprite;
// 複数フレームを所有している場合、処理対象へ
if (sprite.frames.length > 1) {
_targets[id] = true;
hasTarget = true;
}
// 複数フレームを所有するMovieClipを表示している場合、対象処理へ
if (parseTimeline(sprite.timeline)) {
_targets[id] = true;
hasTarget = true;
}
}
}
// 処理対象のMovieClipを表示しているか調査
for (var depth:String in frame.objects) {
var object:FrameObject = frame.objects[depth];
if (_targets[object.characterId]) {
frameCount[object.placedAtIndex] = frameCount[object.placedAtIndex] ? frameCount[object.placedAtIndex] : 0;
addProcessList(object.characterId, ++frameCount[object.placedAtIndex]);
hasTarget = true;
}
}
}
return hasTarget;
}
protected function addTargetList(id:uint):void {
_targets[id] = true;
}
protected function addProcessList(id:uint, frame:uint):void {
_process[id] = _process[id] ? Math.max(_process[id], frame) : frame;
}
}
}
import com.codeazur.as3swf.SWF;
import com.codeazur.as3swf.SWFData;
import com.codeazur.as3swf.SWFTimeline;
import com.codeazur.as3swf.events.SWFEvent;
import com.codeazur.as3swf.factories.SWFTagFactory;
import com.codeazur.as3swf.data.*;
import com.codeazur.as3swf.tags.*;
import flash.utils.ByteArray;
import flash.events.Event;
class FJ_SWF extends SWF {
public function FJ_SWF(ba:ByteArray = null) {
super(ba);
timeline = new FJ_SWFTimeline(this);
}
}
class FJ_SWFTimeline extends SWFTimeline {
protected var _maxCharacterId:uint = 0;
public function get maxCharacterId():uint { return _maxCharacterId; }
public function FJ_SWFTimeline(swf:SWF) {
super(swf);
}
protected override function processTag(tag:ITag):void {
super.processTag(tag);
var currentTagIndex:uint = tags.length - 1;
if(tag is IDefinitionTag) {
var definitionTag:IDefinitionTag = tag as IDefinitionTag;
this._maxCharacterId = Math.max(this._maxCharacterId, definitionTag.characterId);
}
switch (tag.type) {
case TagDefineSprite.TYPE:
processDefineSpriteTag(tag as TagDefineSprite, currentTagIndex);
break;
}
}
protected function processDefineSpriteTag(tag:TagDefineSprite, currentTagIndex:uint):void {
if (tag.frames.length > 1) {
dispatchEvent(new SWFMessageEvent(SWFMessageEvent.NOTICE, tag.toString()));
}
}
// オリジナルより引用、タグクラスのオーバーライド対応 (最新版では不要)
protected override function parseTag(data:SWFData):Boolean {
var pos:uint = data.position;
// Bail out if eof
eof = (pos > data.length);
if(eof) {
trace("WARNING: end of file encountered, no end tag.");
return false;
}
var tagRaw:SWFRawTag = data.readRawTag();
var tagHeader:SWFRecordHeader = tagRaw.header;
var tag:ITag = FJ_SWFTagFactory.create(tagHeader.type, swf); // Override by FJ
try {
tag.parse(data, tagHeader.contentLength, version);
} catch(e:Error) {
// If we get here there was a problem parsing this particular tag.
// Corrupted SWF, possible SWF exploit, or obfuscated SWF.
// TODO: register errors and warnings
trace("WARNING: parse error: " + e.message + ", Tag: " + tag.name + ", Index: " + tags.length);
}
// Register tag
tags.push(tag);
tagsRaw.push(tagRaw);
// Build dictionary and display list etc
processTag(tag);
// Adjust position (just in case the parser under- or overflows)
if(data.position != pos + tagHeader.tagLength) {
trace("WARNING: excess bytes: " +
(data.position - (pos + tagHeader.tagLength)) + ", " +
"Tag: " + tag.name + ", " +
"Index: " + (tags.length - 1)
);
data.position = pos + tagHeader.tagLength;
}
return (tagHeader.type != TagEnd.TYPE);
}
}
class FJ_SWFTagFactory extends SWFTagFactory {
public static function create(type:uint, swf:SWF):ITag {
switch(type) {
/* 39 */ case TagDefineSprite.TYPE: return new FJ_TagDefineSprite(swf);
default: return SWFTagFactory.create(type, swf);
}
}
}
class FJ_TagDefineSprite extends TagDefineSprite {
public function FJ_TagDefineSprite(swf:SWF) {
super(swf);
_timeline = new FJ_SWFTimeline(swf);
}
}
class SWFMessageEvent extends Event {
public static const NOTICE:String = "notice";
public var message:String;
public function SWFMessageEvent(type:String, message:String, bubbles:Boolean=false, cancelable:Boolean=false) {
super(type, bubbles, cancelable);
this.message = message;
}
override public function clone():Event {
return new SWFMessageEvent(type, message, bubbles, cancelable);
}
override public function toString():String {
return "[SWFMessageEvent] message: " + message;
}
}