flash on 2011-4-17

by fujista
now development...
♥2 | Line 234 | Modified 2011-04-21 03:04:04 | MIT License
play

ActionScript3 source code

/**
 * 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;
    }
}