viewing paste as3 sprite parser | ActionScript 3

Posted on the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
/* 
#=======================#
#== AS3 Sprite Parser ==#
#==     Made by zhade ==#
#=======================#
*/
 
package parser.ragnarok {
    
    import flash.utils.ByteArray;
    import flash.utils.Timer;
    import flash.utils.*;
    import flash.display.*;
    import flash.errors.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.net.*;
    
    public class SpriteParser {
        
        private var SPRBA:ByteArray     = new ByteArray(); // The .spr file from which we gonna parse the information
        private var ACTBA:ByteArray     = new ByteArray(); // .act, same as above
        
        private var spriteData:Array    = new Array(); // This will only store the .spr version, ident and number of frames (PAL & RGB)
        private var actData:Array       = new Array(); // In this array will store almost the entire act data, including each actions, its frames and the subframes information
        private var frameData:Array     = new Array(); // This saves the sprites width, height, data length and offset of the images in the .spr file
        private var paletteData:Array   = new Array(); // Pretty much self-explanory right? Structure is paletteData[index(hex)] = RR:GG:BB
        private var soundData:Array     = new Array(); // Contains the path to sound files in grf, saved as strings
        
        private var bitmapArray:Array   = new Array(); // Contains the from .spr to Flash Bitmap converted images
        private var dimArray:Array      = new Array();
        private var animCache:Array     = new Array();
        private var childArray:Array    = new Array();
        
        private var curAct:int; // Which action are we currently viewing? Needed for the UI
        private var curFrame:int; // Which frame, also needed for UI
        private var frameIdx:int; // An index used for a loop
        private var xDimMin:*, xDimMax:*, yDimMin:*, yDimMax:* = null;
        public var mcFrame:MovieClip    = new MovieClip(); // The movieclip that will hold the frames patterns
        public var mcCapture:MovieClip  = new MovieClip();
        
        private var fileName:String; // Name of the input string without extension
        
        private var SPRLoader:URLLoader = new URLLoader(); // Load .spr file
        private var ACTLoader:URLLoader = new URLLoader(); // Load .act file
        private var runTimer:Timer      = new Timer( 0 ); // Every 2/1000 sec a frame is converted from .spr to Bitmap. Is needed to prevent the application freeze
        private var playTimer:Timer     = new Timer( 1000 ); // Timer for the playback, needed for UI. ( Value is changed later in code )
        
        private var useCallback:Boolean = false; // Is set to true if user sets a function for callback 
        private var callback:Function; // the function the user has set
        private var startPoint:Point    = new Point( 0, 0 ); // default position, where the sprite is being placed
        
        private var useFixedFrames:Boolean = false; // This determines whether the frameLoading process is loading all Frames or just specifics.
        private var fixedFrames:Array   = new Array();
        
        private var hasParent:Boolean   = false;
        private var hasChilds:Boolean   = false;
        private var parentSpr:SpriteParser = null;
        public var isEquipment:Boolean  = false;
        
        private var finished:Boolean    = false; // After the parsing process this is set to true
        private var partialFinish:int;
        private var FrameTimer:Number;
        
        // Constructor of the class, either input a string for spr or do it later with the parse() function 
        public function SpriteParser( SPRFilename:String = null ):void {
            
            if( SPRFilename != null) parse( SPRFilename );
            
        } // End function
        
        //  o=====================================================o
        //  o=====================================================o
        //  o==                                                 ==o
        //  o==                 Sprite Parsing                  ==o
        //  o==                                                 ==o
        //  o=====================================================o
        //  o=====================================================o
        
        // Load the file, and call the actual parsing function. If it has been parsed before, show error
        public function parse( SPRFilename:String, useFixed:Boolean=false ):void {
            
            useFixedFrames = useFixed;
            
            try {
                if( finished ) throw new Error( "Attempting to parse file twice. If you want to parse another sprite please create a new instance." );
                
                fileName = SPRFilename;
                if( SPRFilename.lastIndexOf( "." ) != -1 ) fileName = SPRFilename.slice( 0, SPRFilename.lastIndexOf( "." ) );
                
                SPRLoader.dataFormat = URLLoaderDataFormat.BINARY;
                var SPRRequest:URLRequest = new URLRequest( fileName + ".spr" );
                SPRLoader.addEventListener( Event.COMPLETE, sprLoaded );
                
                SPRLoader.load( SPRRequest );
                
                SPRRequest = null;
                
            } catch( err:Error ) {
                
                trace( err );
                
            }
            
        } // End function
        
        // Parse the sprite file. There isn't much I can say, without explaining the .spr file format.
        // Read the arrays string indexes, it should give you an idea what its reading at that point.
        private function sprLoaded( ev:Event ):void {
            
            trace( "Starting Sprite Parsing (SPR)" );
            var TIME:Number=getTimer();
            
            SPRLoader.removeEventListener( Event.COMPLETE, sprLoaded );
            
            SPRBA = SPRLoader.data;
            SPRBA.endian = Endian.LITTLE_ENDIAN;
            
            spriteData['ident']     = SPRBA.readUTFBytes( 2 );
            spriteData['version']   = SPRBA.readUnsignedShort().toString( 16 );
            spriteData['num_pal']   = SPRBA.readUnsignedShort();
            spriteData['num_rgba']  = SPRBA.readUnsignedShort();
            var i:int;
            
            for( i = 0; i < spriteData['num_pal']; i++ ) {
                
                frameData[i] = {
                    width:      SPRBA.readUnsignedShort(),
                    height:     SPRBA.readUnsignedShort(),
                    data_len:   SPRBA.readUnsignedShort(),
                    type:       0,
                    offset:     SPRBA.position
                };
                
                SPRBA.position += frameData[i]['data_len'];
                
                //trace( i + ": " + frameData[i]['width'] + " / " + frameData[i]['height'] );
                
            } // End for-loop
            
            for( i = 0; i < spriteData['num_rgba']; i++ ) {
                
                var idx = spriteData['num_pal'] + i;
                
                var Width:uint  = SPRBA.readUnsignedShort();
                var Height:uint = SPRBA.readUnsignedShort();
                
                frameData[idx] = {
                    width:      Width,
                    height:     Height,
                    data_len:   Width * Height * 4,
                    type:       1,
                    offset:     SPRBA.position
                };
                
                SPRBA.position += frameData[idx]['data_len'];
                
                //trace( idx + ": " + frameData[idx]['width'] + " / " + frameData[idx]['height'] );
                
            } // End for-loop
            
            // After the frames are done, we are almost at the end of the file. 
            // The only thing thats left is the color palette. (Note that even if its a sprite with only RGBA
            // images, it will still have a palette, or so I hope =P
            // The palette is, fortunately, always 1024 bytes long.
            // There are 256 colors, saved in RRGGBBAA structure. 256 * 4 = 1024.
            spriteData['PAL'] = SPRBA.position;
            var a:int;
            var b:int;
            var SColor:String;
            var IdxColor;
            
            for( var p = 0; p < 256; p++ ) {
                
                paletteData[p.toString( 16 )] = decToCol( SPRBA.readUnsignedByte() << 16 |
                                                          SPRBA.readUnsignedByte() << 8 |
                                                          SPRBA.readUnsignedByte() );
                SPRBA.position += 0x01;
                
            } // End for-loop
            
        /*  while( SPRBA.position < SPRBA.length && paletteData.length <= 256 ) {
                
                IdxColor = SPRBA.readUnsignedByte().toString( 16 );
                
                if( b < 256 ) {
                    
                    if( IdxColor.length < 2 ) IdxColor = "0" + IdxColor;
                    SColor = SColor + IdxColor + ":";
                    
                } // End if
                
                a++;
                
                if( a >= 4 ) {
                    
                    paletteData[b.toString( 16 )] = SColor.slice( 0, SColor.length - 1 );
                    SColor = "";
                    b++;
                    a = 0;
                    
                } // End if
                
            } // End while-loop
        */  trace( "Time: " + (getTimer() - TIME) );
            parseAct();
            
        } // End function
        
        private function loadFrames():void {
            trace( "Starting Frame Conversion" );
            FrameTimer=getTimer();
            runTimer.addEventListener( TimerEvent.TIMER, frameLoading );
            runTimer.start();
            
        } // End function
            
        private function frameLoading( ev:TimerEvent ):void {
            
            if(useFixedFrames) frameIdx = fixedFrames[0];
            
            if( frameIdx < ( spriteData['num_pal'] + spriteData['num_rgba'] ) ) {
                
                if( !bitmapArray[frameIdx] ) {
                    
                    var SPRBitmapData:BitmapData = new BitmapData( frameData[frameIdx]['width'], frameData[frameIdx]['height'], true);
                    var SPRBitmap:Bitmap = new Bitmap( SPRBitmapData );
                    
                    SPRBA.position = frameData[frameIdx]['offset'];
                    
                    // Is PAL image (Data Structure: [Palette Index, [Length:Optional]])
                    // The length is only defined for the first index in the palette, meaning 00
                    if( frameData[frameIdx]['type'] == 0 ) {
                        
                        var bgx = 0;
                        var bgy = 0;
                        var tmpColor;
                        var fColor;
                        var tmpLength;
                        var trans = "ff";
                        
                        var cidx = 0;
                        var pixels:Vector.<uint> = new Vector.<uint>(frameData[frameIdx]['width']*frameData[frameIdx]['height'], true); 
                        
                        //for( var i = 0; i < frameData[frameIdx]['data_len']; i++ ) {
                        while( SPRBA.position < ( frameData[frameIdx]['offset'] + frameData[frameIdx]['data_len'] ) ) {
                            
                            tmpColor = SPRBA.readUnsignedByte().toString( 16 );
                            if( tmpColor == 00 ) {
                                
                                trans = "00";
                                tmpLength = SPRBA.readUnsignedByte();
                                
                            } else {
                                
                                tmpLength = 1;
                                trans = "ff";
                                
                            } // End if
                            
                            for( var c = 0; c < tmpLength; c++ ) {
                                
                            //  fColor = paletteData[tmpColor].split( ":" );
                            //  fColor = int( "0x" + trans + fColor[0] + fColor[1] + fColor[2] );
                                fColor = "0x" + trans + paletteData[tmpColor];
                                
                                //--SPRBitmapData.setPixel32( bgx, bgy, fColor );
                                pixels[cidx] = fColor;
                                cidx++;
                                bgx++;
                                
                                if( bgx >= frameData[frameIdx]['width'] ) {
                                    
                                    bgx = 0;
                                    bgy++;
                                    
                                } // End if
                                
                            } // End for-loop
                            
                        } // End while-loop
                    SPRBitmapData.setVector( SPRBitmapData.rect, pixels );
                    // Is RGBA image (Data Structure: [AABBGGRR], It also goes from top to bottom unlike the PAL image.)
                    } else if( frameData[frameIdx]['type'] == 1 ) {
                        
                        var bgx2 = 0;
                        var bgy2 = frameData[frameIdx]['height'] - 1;
                        //var rColor:Array = new Array();
                        var rColor;
                        
                        while( SPRBA.position < ( frameData[frameIdx]['offset'] + frameData[frameIdx]['data_len'] ) ) {
                            
                            rColor = "0x" + toRGB( SPRBA.readUnsignedByte() << 24 |
                                                         SPRBA.readUnsignedByte() |
                                                         SPRBA.readUnsignedByte() << 8 |
                                                         SPRBA.readUnsignedByte() << 16 );
                        
                            
                        /*  rColor = [
                                SPRBA.readUnsignedByte().toString( 16 ),
                                SPRBA.readUnsignedByte().toString( 16 ),
                                SPRBA.readUnsignedByte().toString( 16 ),
                                SPRBA.readUnsignedByte().toString( 16 )
                            ];
                            
                            if( rColor[0].length < 2 ) rColor[0] = "0" + rColor[0];
                            if( rColor[1].length < 2 ) rColor[1] = "0" + rColor[1];
                            if( rColor[2].length < 2 ) rColor[2] = "0" + rColor[2];
                            if( rColor[3].length < 2 ) rColor[3] = "0" + rColor[3];
                            
                            SPRBitmapData.setPixel32( bgx2, bgy2, int( "0x" + rColor[0] + rColor[3] + rColor[2] + rColor[1] ) );
                        */  
                            SPRBitmapData.setPixel32( bgx2, bgy2, rColor );
                            bgx2++;
                            
                            if( bgx2 >= frameData[frameIdx]['width'] ) {
                                
                                bgx2 = 0;
                                bgy2--;
                                
                            } // End if
                            
                        } // End while-loop
                        
                    } // End if
                    
                    bitmapArray[frameIdx] = SPRBitmap;
                    
                } // End if
                
            } else {
                
                if(!useFixedFrames) {
                    
                    runTimer.stop();
                    runTimer.removeEventListener( TimerEvent.TIMER, frameLoading );
                    
    //              parseAct();
                    parseComplete();
                }
                
            } // End if
            
            if(!useFixedFrames) frameIdx++;
            else {
                
                fixedFrames.splice(0,0); // Remove first entry that has been loaded
                fixedFrames = reOrderArray(fixedFrames); // Makes all entries move one down, so that the first entry is set again
                frameIdx = fixedFrames[0];
                
                if(fixedFrames.length <= 0) {
                    runTimer.stop();
                    runTimer.removeEventListener( TimerEvent.TIMER, frameLoading );
                    
    //              parseAct();
                    parseComplete();
                }
                
            } // End if
            
        } // End function
        
        
        
        //  o=====================================================o
        //  o=====================================================o
        //  o==                                                 ==o
        //  o==                 Act Parsing                     ==o
        //  o==                                                 ==o
        //  o=====================================================o
        //  o=====================================================o
        
        private function parseAct():void {
            
            try {
                
                ACTLoader.dataFormat = URLLoaderDataFormat.BINARY;
                var ACTRequest:URLRequest = new URLRequest( fileName + ".act" );
                ACTLoader.addEventListener( Event.COMPLETE, actLoaded );
                
                ACTLoader.load( ACTRequest );
                
                ACTRequest = null;
                
            } catch( err:Error ) {
                
                trace( err );
                
            }
            
        } // End function
        
        private function actLoaded( ev:Event ):void {
        
            trace( "Starting Sprite Parsing (ACT)" );
            var TIME:Number=getTimer();
            
            ACTLoader.removeEventListener( Event.COMPLETE, actLoaded );
            
            ACTBA = ACTLoader.data;
            ACTBA.endian = Endian.LITTLE_ENDIAN;
            
            var anim:int;
            var nf:int;
            var pat:int;
            
            actData['ident']        = ACTBA.readUTFBytes( 2 );
            actData['version']      = ACTBA.readUnsignedShort().toString( 16 );
            actData['num_frames']   = ACTBA.readUnsignedShort();
            actData['num_actions']  = Math.floor( actData['num_frames'] / 8 );
            
            ACTBA.position += 0xA; // Those are useless/unused/unknown bytes that we skip
            
            // Loop through the actions
            for( anim = 0; anim < actData['num_frames']; anim++ ) {
                
                actData[anim] = new Array();
                actData[anim]['num_frames'] = ACTBA.readInt();
                
                // Loop through the actions frames
                for( nf = 0; nf < actData[anim]['num_frames']; nf++ ) {
                    
                    ACTBA.position += 0x20; // Skipped bytes again
                    actData[anim][nf] = new Array();
                    actData[anim][nf]['num_subframes'] = ACTBA.readInt();
                    
                    // Loop through the frames patterns
                    for( pat = 0; pat < actData[anim][nf]['num_subframes']; pat++ ) {
                        
                        actData[anim][nf][pat] = new Array();
                        actData[anim][nf][pat] = {
                            xOffset:    ACTBA.readInt(),
                            yOffset:    ACTBA.readInt(),
                            sprNo:      ACTBA.readInt(),
                            mirror:     ACTBA.readInt(),
                            red:        ACTBA.readUnsignedByte(),
                            green:      ACTBA.readUnsignedByte(),
                            blue:       ACTBA.readUnsignedByte(),
                            alpha:      ACTBA.readUnsignedByte(),
                            offset:     ACTBA.position
                        };
                        
                        // There are differences depending on the version
                        
                        if( actData['version'] >= 200 && actData['version'] <= 203 ) actData[anim][nf][pat]['xyScale'] = ACTBA.readFloat();
                        
                        if( actData['version'] >= 204 ) {
                            
                            actData[anim][nf][pat]['xScale'] = ACTBA.readFloat();
                            actData[anim][nf][pat]['yScale'] = ACTBA.readFloat();
                            
                        } // End if
                        
                        actData[anim][nf][pat]['rotation'] = ACTBA.readInt();
                        actData[anim][nf][pat]['sprType'] = ACTBA.readInt();
                        
                        if( actData['version'] >= 205 ) {
                            
                            actData[anim][nf][pat]['sprWidth'] = ACTBA.readInt();
                            actData[anim][nf][pat]['sprHeight'] = ACTBA.readInt();
                            
                        } // End if
                        
                    } // End for-loop
                    
                    // After the patterns follows the sounds, those are pointers to the sounddata at the end of the actfile.
                    actData[anim][nf]['soundNo'] = ACTBA.readInt();
                    var extrainfo = ACTBA.readInt(); // if this is actually 1 in an act, it will give us the info for reference (eg. head/body/headgear)
                    
                    if( extrainfo == 1 ) {
                        
                        ACTBA.position += 0x04;
                        actData[anim][nf]['refX'] = ACTBA.readInt();
                        actData[anim][nf]['refY'] = ACTBA.readInt();
                        ACTBA.position += 0x04;
                        
                    } // End if
                    
                } // End for-loop
                
            } // End for-loop
            
            // At the end of the act file we find the sound and interval list
            // the sounds are frames specific
            soundData['num_sounds'] = ACTBA.readInt();
            
            if( soundData['num_sounds'] > 0 ) {
                
                for( var sn = 0; sn < soundData['num_sounds']; sn++ ) {
                    
                    soundData[sn] = ACTBA.readUTFBytes(40);
                    
                } // End for-loop
                
            } // End if
            
            // the intervals are actions specific
            for( var intv = 0; intv < actData['num_frames']; intv++ ) {
                
                actData[intv]['interval'] = ACTBA.readFloat();
                
            } // End if
            
            trace( "Time: " + (getTimer() - TIME) );
//          parseComplete();
            if(useFixedFrames) displayFirstFrame();
            else loadFrames();
            
            
        } // End function
        
        // Clean up to reduce memory usage?
        private function parseComplete():void {
            
            SPRLoader.close();
            ACTLoader.close();
            SPRLoader = null;
            ACTLoader = null;
            SPRBA = null;
            ACTBA = null;
            runTimer = null;
            
            mcCapture.graphics.beginFill(0xFFFFFF,0.15);
            mcCapture.graphics.drawRect( -1, -1, mcCapture.width+1, mcCapture.height+1 );
            mcCapture.graphics.endFill();
            trace( "Time: " + (getTimer() - FrameTimer) );
            finished = true;
            if( hasParent ) parentSpr.partFinish();
            else partFinish();
            /*if( useFixedFrames ) displayAction(0, 0);
            if( useCallback ) callback(this);*/
            
        } // End function
        
        
        //  o=====================================================o
        //  o=====================================================o
        //  o==                                                 ==o
        //  o==                     Functions                   ==o
        //  o==                                                 ==o
        //  o=====================================================o
        //  o=====================================================o
        
        // Eh ya, put our info from the actData together and display it on stage I guess...
        // We loop through each pattern of the specific frame and do some magic to it and then display it.
        public function displayAction( action:int = 0, frame:int = 0 ):void {
            if( hasChilds ) {
                for( var i = 0; i < childArray.length; i++ ) {
                    
                    childArray[i].displayAction( action, frame );
                    
                } // End for-loop
            }
            try {
                
                if( !finished ) throw new Error( "Cannot display action when sprite is not fully parsed" );
                
                if( action != curAct ) {
                
                    xDimMin = null;
                    xDimMax = null;
                    yDimMin = null;
                    yDimMax = null;
                    
                } // End if
                
                curAct = action;
                curFrame = frame;
                
                var numPattern:int = actData[action][frame]['num_subframes'];
                while ( mcFrame.numChildren > 0 ) {
                    
                    delete( mcFrame.getChildAt( 0 ) );
                    mcFrame.removeChildAt( 0 );
                    
                } // End while-loop
                
                if( !animCache[curAct] ) animCache[curAct] = new Array();
                
                for( var pat = 0; pat < numPattern; pat++ ) {
                    
                    var patData = actData[action][frame][pat];
                    
                    if( patData['sprNo'] >= 0 ) {
                        
                        var frameNumPadding = ( patData['sprType'] == 1 ) ? spriteData['num_pal'] : 0;
                        
                        var tempBitmapData:BitmapData = bitmapArray[patData['sprNo'] + frameNumPadding].bitmapData.clone();
                        var tempBitmap:Bitmap = new Bitmap( tempBitmapData );
                        var patLayer:MovieClip = new MovieClip();
                        
                        patLayer.ID = pat;
                        
                        patLayer.addChild( tempBitmap );
                        mcFrame.addChild( patLayer );
                        
                        var Alpha:Number    = patData['alpha'] / 255;
                        var Red:Number      = patData['red'] / 255;
                        var Green:Number    = patData['green'] / 255;
                        var Blue:Number     = patData['blue'] / 255;
                        
                        var cTrans:ColorTransform = patLayer.transform.colorTransform;
                        
                        cTrans.alphaMultiplier = Alpha;
                        cTrans.redMultiplier = Red;
                        cTrans.greenMultiplier = Green;
                        cTrans.blueMultiplier = Blue;
                        
                        patLayer.transform.colorTransform = cTrans;
                        
                        var Mirror = 1;
                        if( patData['mirror'] == 1 ) Mirror = -1;
                        
                        var xScale = 1;
                        var yScale = 1;
                        
                        if( actData['version'] >= 200 && actData['version'] <= 203 ) {
                            
                            xScale = patData['xyScale'];
                            yScale = patData['xyScale'];
                            
                        } else {
                            
                            xScale = patData['xScale'];
                            yScale = patData['yScale'];
                            
                        } // End if
                        
                        patLayer.scaleX *= xScale * Mirror;
                        patLayer.scaleY *= yScale;
                        
                        if( hasParent ) {
                            
                            var newOffsetX = null;
                            var newOffsetY = null;
                            
                        //  if( !isEquipment ) {
                            
                                var refOffset:Array = parentSpr.getRefOffset( curAct, curFrame );
                                
                                newOffsetX = patData['xOffset'] + refOffset[0] - actData[curAct][curFrame]['refX'];
                                newOffsetY = patData['yOffset'] + refOffset[1] - actData[curAct][curFrame]['refY'];
                            
                        //  } else {
                                
                        //      newOffsetX = patData['xOffset'] - actData[curAct][curFrame]['refX'];
                        //      newOffsetY = patData['yOffset'] - actData[curAct][curFrame]['refY'];
                                
                        //  } // End if 
                            
                            patLayer.x = Math.floor( ( startPoint.x - patLayer.width / 2 * Mirror ) ) + Math.floor( newOffsetX );
                            patLayer.y = Math.floor( ( startPoint.y - patLayer.height / 2 ) ) + Math.floor( newOffsetY );
                            
                        } else {
                            
                            patLayer.x = Math.floor( ( startPoint.x - patLayer.width / 2 * Mirror ) ) + Math.floor( patData['xOffset'] );
                            patLayer.y = Math.floor( ( startPoint.y - patLayer.height / 2 ) ) + Math.floor( patData['yOffset'] );
                            
                        } // End if
                        
                        if( Math.round( patData['rotation'] ) != 0 ) {
                            
                            var ptRotationPoint:Point = new Point( Math.floor( patLayer.x + patLayer.width / 2 * Mirror ), Math.floor( patLayer.y + patLayer.height / 2 ) );
                            rotateAroundCenter( patLayer, patData['rotation'], ptRotationPoint);
                            
                        } // End if
                        
                    }  else {
                        
                        mcFrame.addChild( new MovieClip() ); // useless
                        
                    } // End if
                    
                } // End for-loop
                
                if( count( animCache[curAct] ) < actData[curAct]['num_frames'] ) {
                    
                    if( mcFrame.numChildren > 0 ) {
                    
                        if( xDimMin == null ) xDimMin = mcFrame.getBounds( mcFrame ).x;
                        if( xDimMax == null ) xDimMax = mcFrame.getBounds( mcFrame ).x + mcFrame.width;
                        if( yDimMin == null ) yDimMin = mcFrame.getBounds( mcFrame ).y;
                        if( yDimMax == null ) yDimMax = mcFrame.getBounds( mcFrame ).y + mcFrame.height;
                        if( xDimMin > mcFrame.getBounds( mcFrame ).x ) xDimMin = mcFrame.getBounds( mcFrame ).x;
                        if( xDimMax < mcFrame.getBounds( mcFrame ).x + mcFrame.width ) xDimMax = mcFrame.getBounds( mcFrame ).x + mcFrame.width;
                        if( yDimMin > mcFrame.getBounds( mcFrame ).y ) yDimMin = mcFrame.getBounds( mcFrame ).y;
                        if( yDimMax < mcFrame.getBounds( mcFrame ).y + mcFrame.height ) yDimMax = mcFrame.getBounds( mcFrame ).y + mcFrame.height;
                        
                    } // End if
                    
                    animCache[curAct][curFrame] = 1;
                    
                } else {
                    
                    if( !dimArray[curAct] ) dimArray[curAct] = new Matrix( xDimMin, yDimMin, ( xDimMax - xDimMin ), ( yDimMax - yDimMin ) );
                    
                    mcCapture.width = dimArray[curAct].c;
                    mcCapture.height = dimArray[curAct].d;
                    
                    mcCapture.x = dimArray[curAct].a + mcCapture.width;
                    mcCapture.y = dimArray[curAct].b + mcCapture.height;
                    
                } // End if
                
            //  var tmpMatrix:Matrix = new Matrix();
            //  tmpMatrix.translate( -mcFrame.getBounds(mcFrame).x, -mcFrame.getBounds(mcFrame).y );
            //  var cacheBitmapData:BitmapData = new BitmapData( mcFrame.width, mcFrame.height, true, 0x00000000 );
            //  var cacheBitmap:Bitmap = new Bitmap( cacheBitmapData );
            //  cacheBitmapData.draw( mcFrame, tmpMatrix );
            //  animCache[curAct][curFrame] = cacheBitmap;
                
            //  } // End if
                
            } catch( err:Error ) {
                
                trace( err );
                
            }
            
        } // End function
        
        
        private function rotateAroundCenter( ob:*, angleDegrees:Number, ptRotationPoint:Point ):void {
        
            var m:Matrix = ob.transform.matrix;
            m.tx -= ptRotationPoint.x;
            m.ty -= ptRotationPoint.y;
            m.rotate( angleDegrees * ( Math.PI / 180 ) );
            m.tx += ptRotationPoint.x;
            m.ty += ptRotationPoint.y;
            ob.transform.matrix = m;
            
        }
        
        private function startAnimation( ev:TimerEvent ):void {
            
            curFrame++;
            if( curFrame >= actData[curAct]['num_frames'] ) curFrame = 0;
            gotoFrame( curFrame );
            
            if( hasChilds ) {
                
                for( var i = 0; i < childArray.length; i++ ) {
                    
                    childArray[i].gotoFrame( curFrame );
                    
                } // End for-loop
                
            } // End if
            
        } // End function
        
        private function decToCol( dec:uint ):String {
            
            var red, green, blue;
            
            blue = ( dec & 255 ).toString( 16 );
            green = ( ( dec & 65280 ) / 256 ).toString( 16 );
            red = ( ( dec & 16711680) / 65536 ).toString( 16 );
            
            red = ( red.length < 2 ) ? "0" + red : red;
            green = ( green.length < 2 ) ? "0" + green : green;
            blue = ( blue.length < 2 ) ? "0" + blue : blue;
            
            return ( red + green + blue );
            
        } // End function
        
        private function toRGB( dec:uint ):String {
            
            return dec.toString( 16 );
            
        } // End function
        
        private function count( arr:Array ):int {
            
            var count:int = 0;
            
            for( var i = 0; i < arr.length; i++ ) {
                
                if( arr[i] != null ) count++;
                
            }
            
            return count;
            
        } // End function
        
        private function getRefOffset( action:int, frame:int ):Array {
            
            return new Array( actData[action][frame]['refX'], actData[action][frame]['refY'] );
            
        } // End function
        
        private function setChild( sprite:SpriteParser ):void {
            
            hasChilds = true;
            childArray.push( sprite );
            
        } // End function
        
        private function reOrderArray( arr:Array ):Array {
            
            var newArr:Array = new Array();
            for( var i=0; i<arr.length; i++ ) {
                
                if( (i+1) <= arr.length && arr[i+1] != null) {
                    newArr[i] = arr[i+1];
                }
                
            } // End for-loop
            
            return newArr;
            
        } // End function
        
        private function displayFirstFrame():void {
            
            fixedFrames = new Array();
            // Get required frames from patterns
            var PatCount = actData[0][0]['num_subframes'];
            for( var i = 0; i < PatCount; i++ ) {
                
                //trace("Pat: "+i+" SprNo: "+actData[0][0][i]['sprNo']);
                if(actData[0][0][i]['type'] == 1) fixedFrames.push(actData[0][0][i]['sprNo']+spriteData['num_pal']);
                else fixedFrames.push(actData[0][0][i]['sprNo']);
                
            } // End for-loop
            
            loadFrames();
            
        } // End function
        
        public function partFinish():void {
            
            partialFinish++;
            if( hasChilds || hasParent ) {
                
                if( partialFinish >= ( count( childArray ) + 1 ) ) {
                    
                    mcFrame.visible = true;
                
                    if( useFixedFrames ) displayAction(0, 0);
                    if( useCallback ) callback(this);
                
                } // End if
                
            } else {
                
                mcFrame.visible = true;
                if( useFixedFrames ) displayAction(0, 0);
                if( useCallback ) callback(this);
                
            } // End if
            
        } // End function
        
        //  o=====================================================o
        //  o=====================================================o
        //  o==                                                 ==o
        //  o==                 Public Functions                ==o
        //  o==                                                 ==o
        //  o=====================================================o
        //  o=====================================================o
        
        public function isLoaded( func:Function ):void {
            
            useCallback = true;
            callback = func;
            
        } // End function
        
        public function setPosition( xPos:int, yPos:int ):void {
            
            startPoint.x = xPos;
            startPoint.y = yPos;
            
            if( mcFrame.numChildren > 0 && finished ) {
                
                for( var pat = 0; pat < mcFrame.numChildren; pat++ ) {
                    
                    var patLayer = mcFrame.getChildAt( pat );
                    var patData = actData[curAct][curFrame][patLayer.ID];
                    
                    var Mirror = 1;
                    if( patData['mirror'] == 1 ) Mirror = -1;
                    
                    patLayer.x = Math.floor( ( startPoint.x - patLayer.width / 2 * Mirror ) ) + Math.floor( patData['xOffset'] );
                    patLayer.y = Math.floor( ( startPoint.y - patLayer.height / 2 ) ) + Math.floor( patData['yOffset'] );
                    
                } // End for-loop
                
            } // End if
            
        } // End function
        
        public function setFrame( mc:MovieClip ):void {
            
            mcFrame = mc;
            
        } // End function
        
        public function gotoFrame( frame:int = 0 ):void {
            
            if( frame >= 0 && frame < actData[curAct]['num_frames'] ) {
                
                displayAction( curAct, frame );
                
            } // End if
            
        } // End function
        
        public function nextFrame():void {
            
            if( ( curFrame + 1 ) < actData[curAct]['num_frames'] ) displayAction( curAct, ( curFrame + 1 ) );
            else displayAction( curAct, 0 );
            
        } // End function
        
        public function prevFrame():void {
            
            if( ( curFrame - 1 ) >= 0 ) displayAction( curAct, ( curFrame - 1 ) );
            else displayAction( curAct, ( actData[curAct]['num_frames'] - 1 ) );
            
        } // End function
        
        public function playStopAnimation():void {
            
            if( !hasParent ) {
                
                if( !playTimer.running ) {
                    
                    playTimer.stop();
                    playTimer.delay = 22 * actData[curAct]['interval'];
                    playTimer.addEventListener( TimerEvent.TIMER, startAnimation );
                    playTimer.start();
                    
                } else {
                    
                    playTimer.stop();
                    
                } // End if
                
            } // End if
            
        } // End function
        
        public function nextAct():void {
            
            if( ( curAct + 1 ) < actData['num_frames'] ) displayAction( ( curAct + 1 ), 0 );
            else displayAction( 0, 0 );
            
        } // End function
        
        public function prevAct():void {
            
            if( ( curAct - 1 ) >= 0 ) displayAction( ( curAct - 1 ), 0 );
            else displayAction( ( actData['num_frames'] - 1 ), 0 )
            
        } // End function
        
        public function generatePalette():Bitmap {
            
            try {
                
                if( !finished ) throw new Error("Cannot generate palette when sprite is not fully parsed");
                
                var paletteBitmapData:BitmapData = new BitmapData( 256, 256, false, 0xffffff );
                var paletteBitmap:Bitmap = new Bitmap( paletteBitmapData );
                var pColor = 0;
                var X=0;
                var Y=0;
                
                for( var i = 0; i < 256; i++ ) {
                    
                    pColor = "0x" + paletteData[i.toString( 16 )];
                    
                    paletteBitmapData.fillRect( new Rectangle( X * 16, Y * 16, 16, 16 ), pColor );
                    X++;
                    
                    if( X >= 16 ) {
                        X = 0;
                        Y++;
                    }
                    
                }
                
            } catch( err:Error ) {
                
                trace( err );
                
            }
            
            return paletteBitmap;
            
        } // End function
        
        public function setParent( sprite:SpriteParser ):void {
            
            hasParent = true;
            parentSpr = sprite;
            sprite.setChild( this );
            
        } // End function
        
        public function getCurFrame():int {
            
            return curFrame;
            
        } // End function
        
        public function getFrameCount():int {
            
            return actData[curAct]['num_frames'];
            
        } // End function
        
        public function getCurAct():int {
            
            return curAct;
            
        } // End function
        
        public function getActCount():int {
            
            return actData['num_frames'];
            
        } // End function
        
    } // End class
    
} // End package
Viewed 964 times, submitted by Guest.