In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Sprite Sheet Anim Tool

update: added sprite sheet preview frame highlighting
/**
 * Copyright Hasufel ( http://wonderfl.net/user/Hasufel )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/35lF
 */

package {
    //**********************************************************************************
    //Sprite Sheet Anim Tool v1:
    //View and control the animation of your sprite sheets (horizontal sort)
    //Renderer: animated bitmap with variable framerate
    //2X Zoom with Scale2x algorithm option
    //Special "woman in the red dress" sprite sheet for zonnbe ;)
    //@by Hasufel 2010
    //**********************************************************************************/
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;//required for samples demo only
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.geom.Matrix;
    import flash.utils.ByteArray;//required for samples demo only
    import flash.utils.getTimer;
    import flash.utils.Timer;

    import com.bit101.components.CheckBox;
    import com.bit101.components.ColorChooser;
    import com.bit101.components.ComboBox;
    import com.bit101.components.InputText;
    import com.bit101.components.Label;
    import com.bit101.components.Panel;
    import com.bit101.components.PushButton;
    import com.bit101.components.Slider;
    import com.bit101.components.Text;
    import com.bit101.components.Window;

    [SWF(width=465, height=465, backgroundColor=0x999999,frameRate=60)]

    public class ToolAnim extends Sprite {
        private const _stageW:uint = stage.stageWidth;
        private const _stageH:uint = stage.stageHeight;

        private const _previewSample:Array = [[0,'DaWomanInDaRedDress',52,true,false],[1,'DumbLemming',6,false,false],[2,'KoopaTroopa',38,true,true],[3,'Phantom',21,false,true]];
        private const _samplesData:Array =["47494638396140035f00d52900d6c6d6843108ffad8cce634a86090e37294b22203265526effffef0000001f1a3c851517ad1821ad2139f7395aff2121fffff75a2929523118a5c6b51350a2ffa5bd7b4a39c6adbd3984f78d8aae849c84a5735a63ad6b634a009c8400ffe7de9d5568af2832000018d6a5428c5a29c10610ffef73bd4a4fffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021ff0b584d502044617461584d503c3f787061636b657420626567696e3d22efbbbf222069643d2257354d304d7043656869487a7265537a4e54637a6b633964223f3e203c783a786d706d65746120786d6c6e733a783d2261646f62653a6e733a6d6574612f2220783a786d70746b3d2241646f626520584d5020436f726520352e302d633036302036312e3133343737372c20323031302f30322f31322d31373a33323a30302020202020202020223e203c7264663a52444620786d6c6e733a7264663d22687474703a2f2f7777772e77332e6f72672f313939392f30322f32322d7264662d73796e7461782d6e7323223e203c7264663a4465736372697074696f6e207264663a61626f75743d222220786d6c6e733a786d703d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f2220786d6c6e733a786d704d4d3d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f6d6d2f2220786d6c6e733a73745265663d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f73547970652f5265736f75726365526566232220786d703a43726561746f72546f6f6c3d2241646f62652050686f746f73686f7020435335204d6163696e746f73682220786d704d4d3a496e7374616e636549443d22786d702e6969643a42333841323544354239454331314446423842373935303534344335393630442220786d704d4d3a446f63756d656e7449443d22786d702e6469643a4233384132354436423945433131444642384237393530353434433539363044223e203c786d704d4d3a4465726976656446726f6d2073745265663a696e7374616e636549443d22786d702e6969643a4233384132354433423945433131444642384237393530353434433539363044222073745265663a646f63756d656e7449443d22786d702e6469643a4233384132354434423945433131444642384237393530353434433539363044222f3e203c2f7264663a4465736372697074696f6e3e203c2f7264663a5244463e203c2f783a786d706d6574613e203c3f787061636b657420656e643d2272223f3e01fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201000021f90401000029002c0000000040035f000006ffc09470482c1a53a4e468943c3a9fd06892b46c46af58e7b46acd7ab15b26e94bbe86bbe574f13c56bb8561f17bce9ebfeb76353e5fdef3bf7e7f598182664a72855e84894f8b8c43535423269494558f46914b95964c986b619c264b9e9f70a19c97a6a787a2aaab9a93a9a5b0adaeb4a6b1b76dab48b695afb9a8c0b8989192bbbdc79bb3bc9f4dbf9dcec663d1a3c58fd0c8cdbdbedbdcc262b2a2a9d3824a4ae4aee67fe8e3ea96ec7ceef0e5d4e9f5f1c6e2f9fad955efe0616b2729a0ba81f30af61b25cf4e9c85081d1e32482e221d2adfea59a4c3afdfc63b002136bc18d2e3c88b19059ed423890403060f62c67c69f02399432e61ca7c40b3e2caff9ba472eee4c9a0e64f40415f0eedb9ae104ea53b99da3b9754a74ca9c08e2a6a09f5ea4b9f4e0b769d5914ec39ae56bd96cdeab46ad49745dfd9445a652cd1b853dbb97d6bb46dddb477cdeafdbb746dde797bbdf6a54a6ac458acfe106fd2798c6cc0b9604899a01cc97253c993384f216b98e1e0d0312b7b660b7a73eace77e56a35d3587412b5873992d209b72b56ccb47793f62d15b894da6ad3d294651c4a41c7c3976a360d1afa5d0624a24e6fde08f975e5db671f17fe5d7b6e90e47bf33defe6396ff5573fe7719f5c31fb34542a61cf9f353b51d9f331b31f330cf9f79b785a0818cd6d64dd07942c038a321a510ed2151a3e953048216bbae987ffa109423518197aa12dc7095cf651a75b89182e81e24ccc2178847b1176e298553d7197496d355e43dc263aaec1638b372a36499044d0f8cd8d38328324249a0df80e7c0f8cf3241c5162472093f17148e266b6ec061503152a02a496c470f99f977a8cc39f4a6b9a80c0280eb9c9dc41d93135e708756645513c5dee59a795f9883113258276d88946634e92287ac014fa22998fb6476069e484b8d693df60ea0a8a9b0e0ae19ffa3549e78a94789a4aa3478a9a2aa9a3b07aea979b11784ba3960c4a8c464c2845e9ac965a496aafbcc9096c9bc20ae462b195b6390bafbc397a6c1fc94274a32c73ca0865560bf9b856b673bcf366a179220a22a4f1580bff5359e006cb2d44eb4aabedb69674ebedaff30a612bac27c64b49be29ec6b2f939b00bc24bf96f43649be0a2d0aaf890c4f774db7042f4ceb2803fb7baebbe97ae4224fc6466c2509d642872fba13ab0b72bbce1acb04c570c97b07a208d79b2abb08f0d99eb9358f8326023983c4b3bdff7e25a7ce2def49f4663d05edaed244c77c34a440d7dc2fc94e231be9d2d7aa48adb456039323ca18137ded1264877d3329e8421d755c48e3c78cdbddfa1b37b5434394f0ca770395b7477b53da37527f179a30bb832b8268ce148b1d57d678576d383055e395b3b6f9493ef928552373b91bd832deb89c2ed18cf9269a6b1429022e39aaa3e7a2ab6e49e54b7ceeff6ceaf602dd7a307e035df6e64717346fe674cbbea7f0c1fadeb3b9b1f26e66edc50bc43cdca7a3fe3bf0b53a3f8866b803ce74505a775fd1d6d7dafeb59cb143b4274de63f887ed8ccb1ffbaa3e91f4479b68fbf4ef3e284d62b79d59a99dffb0668b3d9eda973403a1dff8e26bdff5d6e44841b60eae4e240261ca97a128c1d050f78b90b868f71e2f31f083b383ffa854e83a900da9c58073eb999b012138461ce54c810ed65867e9c9bd3f57038021a3ac686c1411fc67428971412b185e7535e2a96783f1b957081316c22845a92b411f6cf8065fba1d72258c1ad0df180cddba299a0884211f6707d1e945b06af98c31cfe10893759dd08e778c6215effe382327ad319e997b333ce5069d94a601e37c8c7426a2e5b101ce3fd0ae9c73aca2b8de733202355e8c890e1d185f7a323fafe68c7960cf28594dca41f47684944b8ef909a542127ffc5054c2a4f95a3e4611def8886e709b1919bfc22278fd4ca2402928e7e74a38d6ab9bdd0ed51948d54222b4d090892bdcf817da4a4324104c99b38b36ad084de2e75981f666e657fd914e52b035920357e7192d804a4058332483322339405141e31c1e04c61521297f164671eeb094a00c2f3779edca711d159466a96b30f7acc263e01ca050c9ef39d51a4e6143029423ac2726b189967106d16ce8b3643a3e321062c61e9c83b15e8932255a828c937d148baf39eff3e64e0355aeabe4542b4a01915a84d611a514fb264a037ade43269da4c3912d44adc6ca839fb19cd883686a85fe89f6cbc6827a52eb5800ca16a86f4d93236beac805585aa22b3580ead2ed39bb624ebbb7e1756908694adcf02eb56c55a4cac16715759148343efea309b3147af2d4b995df9c952b73aa75a3bac275c4faa35c14e957cfd51a0c31ebbd8991ab63b905deb157d1a589376acb201edaa171debc5d0e247ae9aa52a57af9ad8adfe6bab7ac59c339d4959fef0b3a1b245ed676d4b8c48b04416b42d2b2b5f3bcccb6a81b7ad1d2e887a4b577a16ccb359556e3d73fa5be262558fc1b5ac6c81cbc4cf2ef7bb5645688cbc3a5de502163ffca9ffc260dd64dee66ef4abc98dee74ddfbd6afd696bbd230ee8c907b5feb8657bcc4ad6d8698abdf4ca477b0aefdae76250b5df8229796f43decc28ec409120c801212c870866d8b5bade547b15f258186373cd4087787c2064db088470cdcd8fe76c20ace2a13462c81d9feb799cf8d7188696c63dfa2b7601f16ee8a35dce3028322c7d64df1906b4c32eafe18c649b62f8f256ae42421431c0b8beb9419fbe3780419180390c596cf0be002653943171ec5967d5c660bea78b66b2633506cfce67fc5d9c4ddf93276ed4ce42257191265fb72ba66bc610eb3d97d82966f9c5d8cb74910394602c8f008064032fb06b49d8ed6b09b0430820c533abaeb3cf418ff49c1e2782ca1c69fb634a3fd466a4da3b9d31248356d73da4e4994da1217f674a567bd6ac2b5e4d620ca75ac776d6a3cefc8a04b960073c26c025dcb57ce63fc30ac25fd6a678718dadb33a818804db242fbd7d8a0d0f692370d6b59e7b7d617e4b6009a3d6c508b3adbdde4b6b0cd5d4370278997eca6f6bfe64d6c083338df6f22c1ba878def7adb9b5e99aef1a6453c0001f4db82efce0cc6d4cd6e7a87fae070f0321532bcef754fdae16ea6e68db37d5247e3dae30dc7488b470e86deba5902fb3e52ca437ee93eb83c3f306708ca41cee15e0fc24fe9c8398876aef212e7314d5b68763c884e736cb7bcd85350f3bf383d8a99a717ad4f3778d097ceff04abc7e8cffa726dd78fa4ecd776bddf2002fbd51b6a729d579de75f6f6771717ef2b7173ded6aaf30dedb3e74bb371de348f868db3fee770e4bf4b47315b3cc996e788c98b3e44a7ffb280400f7a1ea08b845cf391318bf7288ab01f3162e7ac3393d800498def417c4e3d1ff95044abb59e0a40fc0e913907a2e936164adc7c8d4ab3efb6e7e18ecb80ffdeb1b3ee9d9d3be862c8f42f05deffbd8f71ef980974dee874f7ae3a71ee37ad42bf377cd690bcbdef4ddec6504b5cb7caa5bd8f9a7e725e0411c144a53c1e155effaece38ef862bb9ef20b23fe00be8f7aeda62120183100f7977fd5777a49e07f657019d3477526a07fa5977e5af77f157676ffaf877ffbf77cafc71d8aa509c86681d697328e677319327ddce770fc9700bec74ada027acc4780c5377fc87778128877a6170020477902607ca7b75c5f577f53707aaed7701f70823b58691a978015960435981fc4a78328c88307757b9155839f26701fe08409a06d400405d2777a017061567881c677804f35832348025488110270854ec88358771ce5a0844b38741f60613ad86433853771e8853cf70143d886bbb67afde185b0c7047e4884591888f5c77a23307bf8470287e8841767865ee685fae7874ed86470e40500c8047cf87e1f2086b3e786c0b78754380294178a88880f5bd80849888609f085efb7868888824ea2816e228702b879aa7887ff29d68a4ff07569c88bb5e8867988787a657a29b7867e2800174001c637587a988cb1e870cce887cf188d608520d8258701008a7ef801d96880dba8872755839c168ed878011f582f89038767787ae9a88e17c08e18d8188f778ed53802ea288ed0388a18038cc73685ca888afd588fcf474b353582fc678390488ff6b8830ae937a9a08394f790eba88dc7387e0572820e779011697ac3648e1de98575089209b99163a58fd58891e2189259389214c97ab09800d6089163080e52a871e8e892e2a88372818b3c198b3ef987bd179482f8832d79903a48550a2406ec18001f908ae18802284001ff485e003605f68883ea8802177095e0375acd810f5c697aff1ff9951420964f184f5d56205de99357c9967a2446cee565f64869fdf8015689956d39311a1870491097fd3897ff985d685366788790dfb89786399643654d04920401809014409555b9968789742e052209809036e9989a0999d2a0984c5099ec7899a249979c29990c099ad79899acd95b2ec59551199b7c399a7f3991e377960920846a399bad4991be89997ef898bb599a7a589cb86995e3a858cac96a838996cd09969be9947a00970940017b999b098001fd278da78511ec8801b8e99de0797c7e65974f479edf799e62099e75992bd9a99de6299adf199e36333c81589e03d09df1a99efb393312559ef0098de929556fd06224608f52899ff21956ffe8d563f68801008aa0fa49458a490295697aaa5998182aa02a194150697a160aa1fa39a28aa382157aa1f9392e0239230cdaa2209a9f22ba892bea9e18f09f359aa0b7a03f05fa9e282aa2d11947411a9a85099e115a11403a9df7d9a3293a32d909951470a2500a6265e28aeef9a16af9a2ec159098536fa979a0f9c957ef68063439a6280aa3ff3233254a013c5aa3d078570c23a6db49a64bea5704baa571daa5f2398141b26b4c908ddcb9a6803a3cc05599d058a8578a943bb3988beaa2795aa4520871842aa9b6a893d664a758e998a5f7a7b3d0a483ba9d7d7a9c183a2ebc69a45b8aa7999a0ca765a9b108a0e0098da8aaa23f97766adaa8dda581ff622a00a51a8e028095cc463e31ba06620aa7e7399558097f0396aa8a136acf089cfd18ac14009dea37a5e810adc94aadccea96d83aa8c8da9da18895d6daa63b93ade1ba97d4fa69e4e3a655700103c0a5d34aae1282244d5610f19aacca5aadf56aaf05d270702aaeeb6aad815a6f9326afea38b0ae3a9ef88ab0c0baac9751b02da1addde9abf41aaa616aa9e93aaf97099dc823814141b1eabaace55aac49027dd12ab024cb44260b6870b9b109bbb24b84a3588065236083cd28ae75285c2d8b251381b353a9b3c32a633d8b04367bb3cca8af1f303294ca897100b44a3bb41b083a3f9bb43adbad03da26559bb3e23ab460fa06d007b441db9d301a82ffd969b4480bac3a2b1b9c9276487b8dfaeab5663b9ea420b663bb971eebaf0561b7fa1ab1751a14502bb46c1b24b414b8023b6b1f6b73c263b8dd39ac6e56b4468b138c3bad8e4b5b97170693db8fecea57af83b6371ba7c6d98cfc147e0653b77d1abacc1a12900b25a69bb0b8b96e6666ab0ff2b9ae3badbcd6b4b7d7bac0faba9beb24fce9b95f58bb091b70ece9b47b7bbac6d9ade200300183b6c1bbbbb189b54e97804af085d1fbba887b258d41bbc22bba7f35b79fd718cfbbbbc3eb279cc24ee33b95d8eb6534fb3c9489bc949b7aed3b089e94bea87bbbabeb0dbaabbed77bbbc56b0658c2bdcdc8bbf87b252d61bd022b6be960c0802bad947bafff0bccbc9ecba10e9cb017a657d5142ca759c1c05a850bccc05580c015bb7f3192482eb4c1faeaab88bb317730c122acaeec8a13f381b6149cc20a0cbeede1bc1c0cacdfb877122c4f2ffcc025f7c3e8bbc3534986323c285310c4162ca8f35b4c4b6cc4be1a000b93b8c112c5361c88198c2c282cb03d9c745702bc52bc7f5afcbfeefbbed14bc6f7fa7a44cc27686cc1df98516c1c209ef0c61dfcc54507763bd250413cc5d2e67b74ac577dacc67864ae2b1209831cc7b12bc1348cc5707c8038c1c88d5cc38facc57a2ca3216cb7cda8c66e7bc9f756c776bcc98a3c89748cc80eecc76bfc86d4720c890cc99cc511ac7cca84ecb6611cb9d540c9778c0eff8d1cc88e9ccb105cc5bc8ccba21c75794cc4b7cca10190cc02a8c68e27062c0ccbde4099cacccc9ed76488d1061385cc5f98cc905cc7cf8c1ec78c04c9bccd8aec78388c2ce1accdfb17c77f6cc6501ccee33cce91702e1aaa1bc73006f1cccd5bb0cf8371cff9cccee65ccbbe805bda1ccf4d50c7024d0590b0c4f9bccf9d4c15f0dcd0fc7cce96e20d42f0cf9a500db56cced93cceeb0c0d3a93bff786cdd0e0d1fa1c8214fd35c78ccfcaaccf0183cddf6c29feecd1ccfcd2d510d37283cd20a00020d0d35f28800100021a8d0446fb07b4b0d33d0d023fbd7f424dd4d85ccba540020bb00049bdd4413d067c82d08c8c084930d50b60d54d5d0d3ecb07ffa624d5530dd6377dcb38fd7f5d40023dfdd5cb1cd43b8dd250ddd66f0dd6731dd51bcdd5771dd7492dd6910b1a63c0d32000d740fdd7441dd8882104845dd878ad00d0a0d88bbd00846dd84c2dd4439dd27a900294ddd7873dd745add940c1d948edd87e6d054f2dc93a43d5958dd7432dd9e1d2045eedd94cfdd4639d07a5d0d38d8dd6a790713fdc0620000048dd003f0d000e20dc2060041bdd06540d000a0000c4dd700360dcc2addc8cdc05ac0dddd34cddc20dd80a3d1fce40d9d0add40208dd00e0dcc90d25093104ac0d020d0000cb6cde3c9dd8b0ddc2eccdd3dafdd30a609528c0d3bcb0d144b0d3e7fdde3fed00fbdddf3d7ddb8580d4e6adccff1570e0feade07f90dd0080022010df100e00ea7d0ecd7de0efbdccfd6d95f32de11cd1dcce6ddecbac0010ded3b62d0826fedc1f2e80078ee0892dda8010dc27de000ab0ddc23de2a9fdc32980e3304ede0370dce7ad003b02de4220e4d0ed003ffddec86ddd4a1ee4476edcca6cdc2850dd42b2e055ae00c76d955f9ee5489e2489c0e4e68d020e10e63d4ee6655ee5678ee5fc3de22f9d081deedcef0de671aee573eee2429ee5778ee6719ee0fa22c9ecdde70af0e70f2ee2e79dde842e042fdedf500ee8109ee5fa42e7867ee715500221fedce92dd0855ee1fb6de715ee009b6ee183cee515eedcfdfde599bee97aeee9540eea905ee10da0e9fbfddcffa65ee9138ee3627ee60d10e221aee7f46d07bceedc873eea331eeae9cd080b70defd2dea689eec510e0982c0eb30fee506cedfe8cde67f80e3278eebd96e9547be062e7ede39ee0015a0e3159ee7cb4ee7e6fedc875e01a43ee3cfdeee6ddee50d5001f29eec59cee8f7feed0d80eebf9ee1fd3eec7960e2ae2ef0aafeec946ef0076fedcf1ef0b50eec076eef7cd0ecce7eeb4d9eefb60eecc9dde8cd2de2119feeadaef11fefeeebaee2302eefe8eeea275feeceeeea125ff2f50e078580f1e2aee201ef001cefeab92ec918bfeec63ef31d1feccc6eee8a1ef0f24ef1599eebf7dedf2bbff4935ef0280feaf12ef5714ef5556fecc65d01c02ef2c25eedff8baef30d10f05f8feb0dffef3b2df1133fe9a9fe0841aff2655ff6458ff61a5ef5113ff7251feae2ce08bcdedfcd3ef70ed0f17c7ff74fdfeb824ff3b86ef8622ff42a5e02896feb8beff7eb2ee630aef47b9ff6a8aeed97aff492eff48dcff92800f998fff98c2ff6e21edc875ef6e8bef78b7ef8fdbefa9eeff3166f07382fe6a49fef5e7feb4d1ff6076feec90cddac9ff9425ffb7350ec97dff2145ffc6a4ff6f9cef4a96efc6fc0e0c19de60480ee845ff9a0ff07f8adfad68ffd50dff47ddffcc67dfd157002a6cfdfd2ef06de2ee6015f02e88efecfcefc309fea3afffdc46f95ebaf06410f04281440016838088e4aa584521485a0d4945ab55eb1ffa905002014168f4825d3d94549b369b5962b048088474249796a42d16bbd756b1e12501ae41c949aba00f612abe0fc9a4ac29296eebaf214f7a086e0148e4a22c98ade2c139fdadee6025003249d402b45d348dd081a021c6a3f15e0dc5c5faf480304060238c726fd427b61a100661de8569f86bc9093b19ee00836c570a577abb118739b159eedca40bc32bfc1af09c6c74e9cced2cfd6ad8b40088c1c14e08da7edf9d2c52c4cbf2576de1c0b58a54f1430fc0c9a53d00dd1422a0d8794d807b14e9321872c4e59a02b0a804784c82d61c205644846bb9a713ca8915248918cb8b83bc9efd94a2ebcec3d013567a7826c1ddb005d3752288005254e3e21ff2409a7d264e172312b1160c0870fc256550dd9871400601f0218fcf4b29e4546c052a12cd784a41b976651cd3a22b582b98fe9acbe4a05429c207e1d85684c57d11eaa01c202cc21e4e90442b67643a68a9c2a09e2cb436cc2219c0f123ccb7eda2edc22744e984e4a1cd8614b6d612c38ae291bf21338592cadae7b9ed097d4668ab2204813ea34f725e3daa04c3d3a22bc9c7096bc7b097d421437a1cac3b18b7ab91daa6b72b0adff0cddc6097760c10254ee743d33497101bc42ae65a78458b7ec15382b9513663a833de7ec1989abae3e102080e5d0eb0f3504d7e14a00af1e942338a8ea022da0b38421ac99d76692909ef0d638cb2b011c2cefbcd8ffe4fb8cc26f06b8b0c105d3a2034609d9f3d0a20018d1a9812774ac4cb61e67ac062714b82b41aa1d092089b604bb204fba278d8cd28c29edd18535e986ec67c7eb72b98b88ed5a0bd30e188723c24cd6b883880e236952a038b6f2818a0e27c9c9523d979033234f3d1d13e63b2eecb4c9c201a2c3113fb4ecd0e789cc1e1b001d291e85ccc8185952f4313832cdaf961d97443111aeb8fa2a2f22bd3b721a53f5b0f0ab0b1f74b23a57016accc61b89e2a9d5238f81358b1af3abb145a2a0a2335096b8ac8641616ecc4b4f65996db69a052d058133a236eda42e61530c7450a890954f4b5614dd12597293fd0eab3b0f5c97db180903652c29c715ee8454ff382405dc342e1bb784ca06b4e39a7fd558f60f3d072ed8e0441565f127a2645d313e3ead4dc642160770474555e132f8cfc66a7c0cd58f31dcd4ba6b7eac14955d35ed564ba15a1606bec8dc9937529c200e88c168f5d4395296d4a9f0e7ae8409ba5d4ed943b80a01416e91c86e3bc946bb1f1bb4f82b3e07ded41ded7afed0e4541d9c5a66b0230ea663421d864aa8a2177acfa9759f5099cf653c6534ba641d160e13a7871560e2791520162d270f4952e365f34df5c6f432d6d8586190ddd841f946b6c858f84e8119bf16e9fb9145b55111f5c298698adc92924767d12b5143a6b3959a517d3d6902ecb61a33b10d7f3dad3ee9b43a1ac54501f1f45aff89ecda5cb4ed7916c316b9ce9df96f80e90a3f1cd9553e522d156acc76a451594e7b6f27a4fd599ce790b943e28bdf7c6dc755e5f4d590dc5fb7d0f8808d226d1623237457fc69e223cd8dae7f0c3b9f8328218ccc8c8e72fef39d83a2a4ad00ec0f825071dc632e1741c061e13da4ab18b482819608a2a2651c0be1eba2052977216782ba0a46eb76e53b5474eb271ba4c28218884208daad39369c028e4e07999c8def5c99a391edf0330072a52f78e7d21ff5600632a551ed32ec8b95dad0e2a0b5454f3e9d480172fc53a12ca2051546495e13c1183ab175302f5623621a8d08458e41e6423733577fe0e0204a31b072bb3a56a01e539c0e42d01d47b3ff5ed540a0409bb8af5650f9d9f3b0d5c28530d263c4c2625e2aa5c849ce3115bdcb8f003a61b2b43d128518ca62641229ca0fc11085d0d24f965cb64a18ba2e5ad65359043569b4d69d0f2ee3438e2a79f7a8fc7c8d1ccaf3161c72b90ea4c1ce6dc0e30f01be18468d9d4e545b3ce3339715c7f669d1415cc9d9bac835810968808d71a395f50660149d30ac0422106739e386c156f60f59ee108106c849c012deec912db2c33d352002634952966a838ce14ce6207c0614989b9ca33c51e818800694a00e35a8636c0419552d5404f49b63eb4a392b89727480c60a29c8be4280c700b4a3e6a4a50ea17532027065a22dad102bab793dfc0987003525d92cff0968b2a4e9a9a615bdd6e668e9a869d5548ff1c4a08368953da2e273a0a2fb4a8d1a09ce76e2f33dc99ce6291f534f76ba7302f0acd0c92a25879c09e2082280000444a022a35eab9ba812c4370de300b74240ae2594215a1a8057bd4e00ae7d7529528ba5aa761216ae0c5ce00b5f5a4ac83056a05e5526c74e6a4a54b8f3ad71152466330bbbbd4ec0a6b224e5ebba09589abe95b4038c6166312982d196568e31848fcbdac88100cc566cac142a6418460bde36065bfa896423db4ad9b94a0e862e132c671b6b59c9e19672cf65ece416a8aa2304d6ba70b5e4720573d0c77077ad61d8ab613f34c105858110ed6d4005185b809f81b7179d1c007bdbebff80f74217bd3f9d151947e5de0a70b600fdbd294e5764bdc1beb5000ca46ff1108c44b84057bed275d6e84efa18b4dc17ba9e4d5b68370cd8e1baf4b52145455b0bc05ada4231b475458b5e0f906208b4b6b70c34aecb08115811c898c6c42dd48d85c1d60a0857c5c5a1022d52c1562177d8c282b16f5cdcbbdff8c22733a9f8217e0531e0eb724c518ec96b94b50c01f9dae8c1ed4b6b7ef52be5b71a386e69616b94472b5fdfad98b8ee78739a1bc0d9b89299ced3458b08f5c2de3ccfb8c0bedb27865505b2058b7973655684e54a2c430af36f7f997de13098fcd9c8a296560e1af48cfb3ccd4d27385586d97191e3b94b204306c63c0eb593938cdf58ffdff5d4a036720abe8c8afcd21ad5460e347ed3cc6447f742c95f16c4a49b7a6b30c179cb94f63598c2706c42cfb7cbfdbb73b0092bd0391bd9280c5beb5e457080f91e40b63691d737f5dad9a391fbd5ed1361d0f0ead609143a3fedb6c48f2fd8c69ec6570464a6d4e624fbb2dd4e39189e52f5416f945c750ffbd148dd652a1ca4df11d7d8c6fcea442d50dcebf45a9c6deb6db5c64352de623723cfaebeb59d8b6d18394cdcdcec0ceea2fbcd7051cc2104de4e429e092ef399d77c8937efb0c59e0d6f77489cd0c2dcadaf79be44a27bd777ecb609394210758639a000550ff7b80fe0f48530919d47a87a01b49d9fac93fb47fde3cfcbad2e67b1dbfbff15a7281d72770c76b0fbbbda9a2116644a2e778ee93c569a69a40501ab57abc75c90c70d1fa1b62b5babd7fdef7aca2b8ae3cef699332ce9164c7c8c231ff41254be6aa6963bd835afa710442acd7acdfcb3a3aeb29aa318ec847ff6092abfa6c83738d92d87bdcb05df7a8b49de1204e03c54089176a3933de403c33dd5ad8e75e20784e69be279dc5b2fcc018c7df9eb9857e5f30e76e98f9df77b683ee7f32edb75773f1195fb7bee652b6e0c85de827061bd6cf5c97ec41322f2aed77ce563d2d3c8f3ddfb5091bae327a3ad140ff48a2f597eef246641b64eaf008d8ff23ac1d40690fcf4609d28efecb6cbf416af388822f58c64f44ea2fe0a4e03dbff8503810f046baff83a705ad04f04764f0347cff94220fce2aae924700d98a832a42efb661043b8cf2298e805ed00e7e64db6b6af0799cfffbaa83cc84afb6c27eb08f0083930e9924b9cc2ee2b9e70eb44afe6786e0a492becf86f028d89503e509c482bfe441007a55039c8aa0cbf100c61efff746432f68d0adb300d7e70eaf4ab19f48f0c6bd00ea7e500b72b01d7b00fb380e636efec90f001256e10ede19b5c2e1101900b09b1109125ea2c71f4a22e090691ca185065f84308cbf004b1507b522f060771db8a0f08d1101477d00a27110b6ef00d1f61095b31009cf015abc0f770904e1c20beb24e45a6cf0947f1106f4f0909ab000e40450440187dff706080700bd30dae92d177ae100a713059a403dcc82da3ced0132b23f1deaab19cade5483106dbab9dc2b1df9aac1a70e71273f0aeec291deb10169527e95ac3ce9cc103f60aae9af1100f30c79a21dcc00d0be52309ff500fa5adb3d87169e010091131046e2e1af991f92890f25ed01235311dc7f108a7c5f9360f1d3b6bef44507b5210dc8c0e17ad2016bb451ba5af1aad8f21bb88c0a6910763ac192f924ee22ceb106aec0a6018819061f60a1995d1167b7214618f6aa48db466122d8ad226a96660700ed4622ca3e6f10a54924e38611ffb8dcb8ac3f83c714f6a4e2b3772ebd0d012b72768b4721d770e0d45ef113b402b2dc2211f7116e62020c9ff8db07a2c196eb06bdc912fb7eb35e0b2ed36ef12d94915638fe4b4b20d87a8302fb103536f163532043952f49ceff6c4722c1bb123ed86b3486bbe50b20a966617ff492a5b921c45933f82722983b1293313137f521b93d1461c24fd3eb3121d3304282c362dc62517922f3d121d95f2683e930a7c4f152d9033c34dfaaad20a88f12bb352234b663941b320bf52ea2e533a89d331dff02941d2bbb0f306a54e0be9042de5d11a8bb12d5daea7eed2d6aa8114cbd22ccda501c84522c9aff9bcd11b2db15d4ee2d30a4be686c838dd11403111324392137be19bb4ea1965512c4b861c49d232f15298d062385340685e13d4e0670028b4420df0357d71dd78ff3319fed031c950287fc6415a6f189bf30d9730194f74b786f3fa0c73103f4643531140898a0fd54f5452b1320d7213a333e46e123fc3920fd526e460703b53102a06512d1501771cf3237f122df9b02aed1311fd6f30ed5120f9b03d7d344097d4db6854111ef43e03340a97a849874d278cf30d39d013d1740ecb10abda0e411f91185db348a910aa44b137437341c93089eaad00b5f39ff8b0770480422bf119176bde96b241b42e33fdef197153f1a691411c24eb6ab3029d4f0185f22b128c355fb2e60ab5321430394fa84f17524997f454631353b1b342df5434ffef5463ce4003a21edb74414f558b90b42c4ff33c6dd549fbef36a5743cc9c556adff747c2a9030d192ddcaed4089b431c3142d4f75d8caf1f7ce945281f2549df44adf7357d1904e20d256a16a009e1441ed94312fd23a7bf53da4139c6070f4bcf5cf542524fef04ddb4901c52d8430f31b16b5242d55506f445401360ba3f45aed153eaaef1bb27445e543611fe55ff5f2236f132715102e80ae19c7f537afd5413676219c114065715fc5afabbe935289944989b07a7c705e83754b4f365ee7d5f848d05a4ff6257f93329d3559af55443bf03667b5217dd6311c8d14ef945a558ff3f42faed4922874c24de1934853302c5bf65cfb6f52fb527cb416584d76cfba4a2fd79553e1d3646b87620f340beb9165891064d1563027354abff67a76ffb31f07334ac3b2761a043e0cb6623f124f9f12e1ccb0359b133e930eab3e879072c6fa54f629c156fa88535d7b61488596612c07557c101383d558b76272b0335b631628854a3ab3354faf112d1b4a2feda630cb72ac2a8b585392722bcf30b5d075c7660fd63669c5b564d1d25126508340404b6775693db2e6f48f8e543517f1a84c6f8fe6cc925a79ee64f8075dd3759dc6f66e0dd782340aaae2b512a19477b722b52e2d2ebb962d0945184068365594769db173310447fa366dff96728bb17a3a2d7905533c2fb67e31d564d8c91dda93528df37c134c8fa2965e90a3f714b4662df7c9e2925617383fdb8f84c8b25ba27075c9c5682b58683b16ffacffcc1e4892755b17283503684f9353f176ac3aa9ccbe174b2df23eddf47f054a836d1027de404b61b84db5d0789d967fcaac0fc02887b3107a93ae83d0375dcbd4789d177a6fef656e844e1b515d7fb3882de66d7baf7c63b88865b34642146e1d922dafd1be206353ffd64753f051b0078009b7744ff7c9ee548daff84da7f63cedab8254061da260019eb47147d8726369eb64b73225b8fd7e955cdb953b2fee73edc6702fd2db5e7667bf7890333875cb2f8251d84dcf73929d34771f71774b313d71640f96240aee1686bf524b3b21ae68580d166024aec394936e6a25589557790d8098798b915a47b6fd9e8a7a01565dcb111b3b8e2b33b338059854cfffae93d4170b796e5e19357c67b300bc48529bb954c3185eb30a8ee1b69a3918077168b760d0e6e2588091567bf9076249a2955b3911565496e1307a29b842a1169ada2e683bf63dff175f1779810d925c32779f2dd991994ff5d8c999bded83eb995c1f72690754f47a2a9e6d10591f31871f333d55391140409d5f6577ef336ead9692b1409df118044c19963d705fff580f46622490039773b9231b1247fa70315dae661b5a7b850125eb728e71f8743b3718a2959a435369af795ffdf960b39476f1732b362b3de979f2061362c37353364b04cc54a0fb6f68a56e6739c338ab82a5331a77e1548e67f7ff862878c0488fbd8f9f593586f379a0f7d99efbff799ae1da82c9ba9f9f7a1d4872760d3a68ac8f6a628f78331922674ea24578ac5f702e835aa5d5792432c1a5e1d4a3cb95f7587a0176a1a4cdf4a44dd6122afb10481ab397d6a2bb0f8c8237696dba5a9934afc5d6988b77685d4eb6543b6df353157b9aa0d313a98f757f23fb4e8ffa8aa3fa412913b4253ab60bb1b6b3384c87b732f018055a39addd90a1d1f492e1f4abd7ba54e7589295b811abd3300dbbb7f5dab6efda8589bbb031f88ba5f6ad55773c6359b0b194b07d9bb72156ae0f70bcd3a0b15b595054cf9411361345a1b37f228729ba18e99b95337aa4859b81fdbabf03c5e57498a85d98ae678e4d5d736775782e7f597843788e2139c17bffc10105d493e17bc0e9f1b777fb4f311b39445c79355c8251fb4da504acd5da069358970fdb1b973bac273049bb197ca35a9b5f01b8dbb991d11b6071b4946975c8d31bb5111bc91578c3c7dab0dddb124483b46b5cae339961fabbb16fdc8c973a6e612fc5af40a3a3806a333bb1215c112a7bcc019ca1b114ccf9c00b3e9ba21dfcf7dcfc0a04d4b64dfccabd5b811b13994f37b9517bcfcbcfc3d9bca4e75b148638be031b86499b114c456b0534b8e1fbc661bc581bbc6c197c57f1d829625c0dca11baf3945dab266d4f59a9f5fccca51583b55acfeb3c0bf65abadd9ac37fdc300b3abf7d3a4b5f41345ea5b493b8bc29afd5edbb9577c1c1cb3b0a5bfffd222cfbb2757b5aaff1d82f22a3d5fcc911fbca5f21d9cfc0a489fdc15b3d886d7d49796e57e9fc40ddf19ecf93a30f507ea31ab139fad6655dc6b536cfab5cb9a5644b5004d24bfc1027dd0c9adbb9d7c000a7f56633fd124922a33bbd104d9d81631dd2aba6d55b58bd05dbc2ff5ad5959a689d3d17effdd26f5bdc8bbddbafdc78a53c21a6e10db85dbfef5438381b391a7ba3399a31b3a4179a1bcec114969b53d013e1be334168c5555fb15a11f0bbcc3d10dc331ea32981cbaf110eaf9ac927f0bac3d9bcbd11e29fd422813bdbf1bcddd56051bffdded1991ebaa1e03d5d782b9c611e9c43b840a4f9dd0f9dd1e72b1abefbc30bd439e96116cf6fffda22cdbaf74a9ccd0fdd614f99e97b96ea9f34ef99fef6c29dd4b9d3d05977dbdf60317a0439487ea28fbdb2d59959406077339d4e9241d87f62dc097f4a2b5e0baae24ccbbc5a9d3dd9e31cbae5435c837e0f7afe28437ba19b1ee91326f2d9fb28c15ee65deebdb158bd35bccb97884c87f8ea979e5397fb0c5c99d307ddeb77b530ef74b9f71de5dd5df5d13eec19269db91e160b7dea75f7ff12b8fcea9ecddf78f37571e3c399e22bd6ef93b89351bdffe21c8cf27cc33d70dbb5bc47949dfc0bbaf149fbf1e1bca319bc5baa0123221f0842a113b16824864aa521b2444841a3d2291584420140c22df388141a95ca27b52c5d00d220efb6982c799bffe2b1b96c45ade3a7f6690e8fbfcd91d5458180a81d7521f58929c6f9d1114611f8717935263916196a891180484a51620a352606ce1da6012cb42e80bc2e84428d72f125cea12add61b51ab6868eee691a714142aab20287feb981e9e9426e9518668132b39916b71d47ce4a35bbe59e2a450f7e4f5ecee91d279da3a71c72ae72eac969bfcfbabefe0260653deab6a40f3c28fc38a1b98227a0b430f9bebd52a88558b6707d1e429468cbde3045a830d651b5b0983a8b61fc80ac22115a173fd020a5942232cfa26d7bd67134f76d14294ded8e5453332fcbce5cc6ca6d8b764799af5fe86ad97a56f1182f58fc643153328ce397687e78b19a45e994d497ff029324bb26c9242a36a5bc7a2b3a7520ae72300bd22aa995a1512778e36551e8ef0a40b3f8fea6d8e7ead0159a45040e2cf1f7e02f898e19fd741393d002cb148f88012d1971bcc696ecdd7aeca960556753eddd45470f90686d7ae312623c92259171a863870251a9acea8627aa29244c584db0e1d36c1f15b3b4a9537446a352f4ca4bb1d8d0a959c2a53618c532496393d2e51a3e6d3040beb7d9edb659942654f5c3fbc55baf37cedbe54acd370572ff2487c765c585761162072d469863903111c2829cc0e2cf6cfc75934880660c96c567e2eca5da862a613111574bd4b71a3c604d441c66e9d525886c2b91540c2486a9189c50e0ddf3e18bd4a063ff484f7c216361811d12d5dc75a5f4171d350a51070b3c3ca188dd67bae8c69d927064c29533dd6c8755308e4ce3e3495f05a5561d04b8671b7c021932255befd928d088853486618831f6945f906830d58a6085d596a082932124689e081a17c29d5134d54a1a96416691a3a44131e96e8691e9a77ef4b8085aa83906e9e07737b959a78cdfe8e61871d1e0881b2134ba05e29e7cc5398b3c43fa275d72815a98a4ae4b32895447c566c96041546257e56fbb88b44f515abde5a5aabb7428e69864196bed57f4a8b9a64937b609a635411a7266b7d71ef3286359903bd77f00e2b51885ef2eaaee9e8f42fa8ba01756aa19a6be28eaa0909989832960b4cee5ff13bf5088e4614e2832e42eb82ec6ebdf88550de162341401174a8707a6f6de7ea85693ab24f208e72c91d28d479e629cacd87295cf25688b74aa2ca6ed53c4167be52e82b9f233b5d55a5b5c32613d4566d04963a65b163e877459c67ca6a24ab8b9edf86376901170e74c07dfaaefbceed47bef500cff989ea7f03008a883952af2f0198b055ba2cd863aa4308be5aedb9bddbc94c8d17f6df22bb516589b64abacb999fa1d5ceca0546ae1b5a93b842196dd2b94ae5abbccb878f4d86b957e074755c9b14c265af45f54de8c338caae9864779dd9d1df889e2394835210438ad8b99514be4bb192c333abbd9a3cb63b9817b2b7f0f325b87e28ba6d69cbcffbc2dfc46394f720faa5e84dd57f9c239f46e8ea67062ae106870aa82fbbd0aa1d2f3fd98dda5594679d9723cfcabab1902ee6d2bc3826952d40de2846c65f2fbdf9eb216b3128d4c580a5443fd92f724c2944e4aa7db55ea5c92bab4b80e317bb3527f36e1bd2b20062ac58ade2336e7a00d3ae3635e428b60a81712bd91ed7dfa5a9a0dcdd099f6ddeb6bdd902044acf2ab1a5ee663cf7918651620820111ca38875a502cca77bd1cde2a7dea5b5fed20c8096208f02f4b4917aaae063f4c0dca1a856a1c7f1ee6420359b082657c1ce4f2c7ae9d5128791bd354ba5c42bba5ad020f3153d92c84d2b25715a9784d14615a0ce1a49e088187b713e308a3a2ff360a21a931a4399b7db87242c288b1448fd4a11182c21cb819496f7e840dcce801b7cec46c64cffa1611f5118b0e152889d2d88221eee70a1100f389e05ac3317ad3c357ba425306431d68b63805c56421906a6ca633c783bdf381f17ea5096463f2a00b56decf0a933ad825b327079ae96750649c23b41ec889afe0c59ad72c27924010cc0195883569a914b45a65af49b2861e863c1f8a30e9ca2db2ec8b9184a2326359cb9ab5483be58cd80bd3894382ea6e13d63ca60f612998e709c74bd4980721215230659a937ea6e4681d24650d6032669d7a9a57f3d4e7c4600a733918150f4be1714f9d5eec08da34034e5fa1cc8b1261a88540d260d4e6939eff06a78b865ce525a01a92a35e4f7ee6ebdc437545c0655e52ab1f056949bdba1c7932f57b387d623cd019d06152c8813a05a6b4d4f7c98baaada15d65e4024d79c4b16a327e133d612c736955125d71b07924c21bf1409a0a2907ac295de9619fd9942742d19c3b53c32929b9d62712703fe6ea2c693e2b0277bed357f974e65a87d2570a39930a6b2d003e510a02a5e2a97dba252b6c9d49b88d2ab6b79822dc57ffc1cde27293b4014de3a07e05009c1e556b943cee6ef9685adf0ac5b986742e4e632b93e682b7b8ddf42e6016f857e3aab3b25c13a844927bdec08a90ba93e2ac3c71b81cf8f275a3f2ccebc8d467da02b46f9e84ad69694d5b3b6b4c4fff9c7b4587080ce0609cfe16ac81516f1d1afc59ebd143a7e48d8285bb8b9c585278659c68ef91beb7e00d12b7a1ccc5ef63df8556150356b9cb8dec7d2562da1f0af2c4b911098dcf6acfebfa169fe28dee67375cded3bef78a46366560d2f863cc96d5ae0b1c4f327a3cb2109328b2f405ac78578ba9cfaaa140438ed9164d9bd312c738ca051141010af060ba3a749e6176acc21adc6637173522fa05576cd98ce76042ca7a3534720ad86c80ee16a2b158d61104d1dc181d8b30c9cead6890c195e7e782c53208e5f15931686658b26cd3a0106616605ae8603af8d022206f849bfb523be399d010062fa6ad7168591b02a6423133a1574a654e7c36d4e4ffc56c56b5c669f1aad9a79f668a381dbd680e7fba7c5606a97f0dd06660aa5a04fc906f3d9f5de83b671b9890c21e7d658c296b5f5bd5d0d6368b8c0ceb0e4b01c26edd3094efb95d1c12bad0147a2f01217dba68c334d7985db2d60c000bbade14d58716ae77798d6d361fe000b766b5c0897d2e541720e2125fb5bbdf0c689c3a38e26e9675aae10d85d91680e304b7a770151e6b77b73657b97eb0c12d24dd32a73adcf1362a26e7fde59cebdc203627e9b0ef9c72402fd5d1e65e33badb7ce8899f3ce69eeb33ba111df5b5fac2ddd77e78bc3dae72237bfdeb0147baaca1cb1ccc063cd9fe55f8c44d6b807c17bae4c16c05b60f7de7af0f5be1486ff0ffd3230ef5bc17f9e4aa3680c6dfae753cabfbd487d678c4f1ce5aa7f35de51d66bce31f8f78a847bef024a7b9b8396c6dbbbfbce14d7ffadfcdeced29f819f2a5d776c23b7ef7073ff3e003bfb97f8d8e6ad4737ed56a474cea53be7a9affbde8e9c67cc9612febe1775ef0a0af7c6c1ffce775f33df8c37e3ae4a34e7a07c3ddc272f7fce2fd9eef0efbb9f393d7bceb512d79bb335ee260dfba85a16f6d9133ffcbec273ee9e14fefaa735df04727fc01e25f5afcb75fbc1d9d081c40cad19bed919df2d999f4d519ba859bd8e194014e1fe4599d0226609f19ddd3899db5991fc9dd5d02821f9bf9dfcfcd5fd70da0046a9dde41dbe0855ed1a9e0d50193ffd3c15db6dd1df4555fd9c560e87518ffa1a0f0c11ad4bd190f1a9ee8ddddb5751db651de045e9b11465dca659cc68940049057d3859f00a65c120adf12f660f8695c011c6011f6e0b75da1c829a1eae15dd5f9dd08e245eff9de107e1bfc8d5c19fa1edec19a13aae15ffc6005425cff31e1fdd9dedfbd1f1f8621d5bd9ed8156101e65bd5dda0e2a1df203a9322ba19f13598fd955f06729c853da1fa915cef115f26f65fc7cd16e6c520e379e1f4995f831da1277e62c3ed9f1e625ce34921063ea021a21a2c4edf2c0a602dae62f345e2f6e5223051a2e545a21e6e1dffdd21838d1e31365e0c1e2332b21f083e6105c656043c5cce49de32e6df04061eff14105eb6eda2e8e12287b11f228222c89ddffe355e399aa3fb791fcc81dccb815c3bd21bca8922127e639f451fe779de247661337e03b665a028a25f30b2561d2ea20866e2a1c5226b811eb849de1242e142e25c43caa0388ea13ce29c41b620c41120f9595ed31d6434422111fa9e4372583fa663c3699f259e2414f6a17751231bb65d3fbe24d5192410422146daa4d1855e2076e43d1624d025df1efea43f32d84d0ee54016a051ce02403a64db296529de9f35ea60f7a5e1f4752105ae5bc81124ce65a50ed61dfc4924ce65620dc2e0fb4561de056201a2a0f9a1e55836a09f65a5e4bda2c4c1e5ffa59ec8f560b8f19f1bd65ed3f563145c1f5a1221ffac89dc4c82a423624a04c4e49d1de625fa9ddc316553a29b5e42662f5e204356265bd2a535326003b6995eb6653e12de6486829de9a52486a55f326459c263048ee4048a66fbb15d6c8a9e686ae0d56da662fe1f4f22dec97922fec9e10deea1dfa5dc5d82a66f5ea227ba19727e191bf661714a9c013827ef51a459a6c05a16a0835527d341675b8666e16922437ea7ca3918739aa619c4a4464a206a92627a565862be5c37aa226ff6264f72dc6606267951a37c5ea2762ea51f2aa7fe91e26726a749c61d73629f80b2a47b8a5c4a922402eae2830265b5f1646e4aa79b0568843ae4aafd640664c03232e670c6da1e82a8df75a775fae6ad996888da25ff8322283f9e68ffa5e89ab167db3de18c2ae4343aa5d3615e8e9ea881fe454c26e68f461c8886286b2a0c636a24541ee98cc2a77a9e274b66a7c43da947521d484edc5a42a9eb51a98c76297f36e9723e6988dae77dc628909aa9925ae8857aa89a1660851e2805f6e795c6699496c19846617106694daa0f915ae388fe24e351a79101ea9b49a17442a89892665a2aea8b8aa950a6e51ba6dfa44ee3a106532c3eaaa53ad3a1aada426e6a8dc203935aa3a53e2a9bd6593e0293a6f25fa56ed87aca9da66a68fa8d278f46dfaa0227adcae992d6dd83b12aad9e2962f467a0e66afa05eb90f62aae526a811a6ab24661a2aae252e229150c2ba2422bb00aa9ffb0aaeab36667b4faeaab5a40b886eb88166b1716aaa14680b88e2b70a267be31a6ba92ab5cf6a3a816c4bb8a2bb98ae17b129abd8e2ba886278aa2abba5a8044ca6b1ad2eba8a6ebbd5aa1bebe6ac2f66b1450e3bf6e287f3aecc02e64c4d6e7b452abc3e26bc41aabc6522bbc822a80662b69f0ebc07a9e8282ec14542cbe16ec76a2ea9272ecc8a227bec2e4bdba6cab8ae5c1a2c3ccfa6bcdf2ec1655ebb7c29d7a6e6bd00aedd116add10a25d2fea9d22e2db53aabd3f26aa952ed6236ead59a2ca6726ad4a600d76a2db242add74281a72a2bd97e6da3766dd4822dda426cafeea8dba6add5ca2dc45ac0066cc0bad6edd7de6ddea2ecdea62bdee66d41d89a6cb8e2eddfd66de0fa2de10a6bdfea6de21aeee0ee2ddf3a2ee32246e45a2ce0f6ade426aee23eaedb7a6ee642aee08aaedc86aee5e2c5e94eaeeae2451000003b",
"47494638396130000a0091030000b5005a63ffffefdeffffff21f90401000003002c0000000030000a000002759c6f308aedadd883a0269b16c2ab327f449b540921605e24faa167daad8224d4470dbb09bedb06bf0b01078200a278f4118d37e6cf4954229b4d670d3a350460832dc24b0d2f8da6a23580857a53602d17fd255fe15ab59d5887d1c707381b4d06c864d64756e7277803239502c4a80819d5685200003b",
"474946383961be003900b30c00cff0af9fc070ff00005f000090f8ffa00000001830fff8d0ff7800ffc000fff8ff000000ffffff00000000000000000021ff0b584d502044617461584d503c3f787061636b657420626567696e3d22efbbbf222069643d2257354d304d7043656869487a7265537a4e54637a6b633964223f3e203c783a786d706d65746120786d6c6e733a783d2261646f62653a6e733a6d6574612f2220783a786d70746b3d2241646f626520584d5020436f726520352e302d633036302036312e3133343737372c20323031302f30322f31322d31373a33323a30302020202020202020223e203c7264663a52444620786d6c6e733a7264663d22687474703a2f2f7777772e77332e6f72672f313939392f30322f32322d7264662d73796e7461782d6e7323223e203c7264663a4465736372697074696f6e207264663a61626f75743d222220786d6c6e733a786d703d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f2220786d6c6e733a786d704d4d3d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f6d6d2f2220786d6c6e733a73745265663d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f73547970652f5265736f75726365526566232220786d703a43726561746f72546f6f6c3d2241646f62652050686f746f73686f7020435335204d6163696e746f73682220786d704d4d3a496e7374616e636549443d22786d702e6969643a43413045374144454241373831314446423842373935303534344335393630442220786d704d4d3a446f63756d656e7449443d22786d702e6469643a4341304537414446424137383131444642384237393530353434433539363044223e203c786d704d4d3a4465726976656446726f6d2073745265663a696e7374616e636549443d22786d702e6969643a4233384132354437423945433131444642384237393530353434433539363044222073745265663a646f63756d656e7449443d22786d702e6469643a4233384132354438423945433131444642384237393530353434433539363044222f3e203c2f7264663a4465736372697074696f6e3e203c2f7264663a5244463e203c2f783a786d706d6574613e203c3f787061636b657420656e643d2272223f3e01fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201000021f9040100000c002c00000000be0039000004ff90c949abbd38ebcdbbff60288e64699e68aaae6cebbe702ccf746ddf78aeef7cefffa9c54223041a8fac452030bc2899c8a834f4843a97d6a9765b5102004dcbe29be59a93c22269fc0d77bfe0b35cb52028168afb4808381cdc140b7e60801c6a2087733875798d7a1f697d7e85128283691e4f94199a8a398c77a19b574c7d8f187807604ba31355ad6258b05a698974a078b99001600779ad780a7f0065a8bc719064b388b5308cc1cb88080476b977d16c82bf4479c3c89cc7df1d6cc4d186d5db2da08ee68608ef760a0809f4b6a87dc1a74e8d82e25792ed2c950b128f9dba78d6da1179378f21bd3c09968df1c58f5b2355a322f9f9b3a196908d84ff148a41280a0d495d41ded14b30afde9d881d271ae4e40823254da6d23941174ad8aa62cc4eea43b1601aba5c229da8a4d772653d22ac1c0ded22b553175933474aedf94a8c44a3a2aed91351145e9ea66399394450d4e953704caa5ae4c72a569bac5d8442537615681786f1d02a49ea6aed5288690d2d2830a0ec3bc72bd942bd5bd149ad5f7cbbb0f95359b3de3baa080592b550a5c30488ebae59ca72652e9864052c1050c0712d86922783c1eb8a67aeccae4af991fb975a5821c23066f1e2ef6f53b42f0797281bd9ed5b44bf6e9f2e9bd89524de0cd6f1bb148b0945de8e03bb4e659579f340ac9b3a1de357f1dab66e15ce1632df76b37139a1f719ff467601b0953e909d86581e9979b1d12642dc275f3d0331c398636c9dc6927ef8adf7d87f999cd75978b884c591130112175e7cae45e753137c0c37951017e2061953fd74d7856cb4f91721431cb654cb1f1ffd011b245bb95194710975a7cd816150c79475110903232be701b25f8f40a661a395aa75945d2eb8d5f321151da6b1d183472299557a67ad17d3818f24d8e17a516239137262dd5166441f82595f2002c8e6918f3aa29266910f2ed0a69b15257898028f2a0ae56218deb8e155948dc98f6cd97599063fc07192467f679a40663d964cf22361f9e821656b2e398a0d9f9f226a238a93b093ab4781c62a50218978e9169196604222a4b510d268ffa2730d31eb84d765c2a7764b7107a18849cad612b2bd6e75e268cbe137e49a464a1be65cd9397b994e7bf06327b522cdc62334a22636189d6235852eb25595d155258bb6ea2a4c03d354d5b58d8e48d698366a981b22f7f6cb56a29a707b476d42324a6495dd5855c931512ebae6a90897aa5992bb155a8ba1d01016dec6ba024996102e9b5be42cccc928c4008dc9972c7f550e52a1776d0462aeb393d84cce4d4f2ebc188fd909f04bc8496dc9f176a9225200ccfe9e3ccea104cfdaaace1e19a03440ae8c792dd9e15da2a5241a4b3bc0d702d453a84b20e9e729a2b0decd31ab6783988c2f05ff38f11506c3482a1e39ffd7f872c7685ce7d709348679ff6317a94c84cba0fac9d67b88001df47cc8ba4616401e3d0bcb603ee37a07185fcfe6369f93507e4c9285651ea1ef8e9031a818158b65f81a5ea2d5b4ea378f0139ccfbe9a889aff28271f7de1159ddd32febaac9bb2b6a8c5a93b263db8bd4b932879753e2d94e4723d5d7680f4ca7576f93c6e6f6ba44aa3f13710b8c54e48144ed56950074a5af7fce5393ab6ca6aaebe52d7b0fcc0802a1041fdfe18f1d720bce1738032f548cc7739c10dcefe871328fec810fd7bacbf1d6803ffc41c512db73d86d80c78fe4486764bc109621d8418ce175c174684b1df34ef8bc34448e0ef3684c5b1ad3911cd20918b2e3a1ee70850d79ad4b3123ac47d3d07282a9abd92e7e1d741f8ca03511d9418b44ecc891666038150fdaf08c953085d9b453ad3d38506f1104c2a1e0083eb8bd816d90309a7e58a73c8ed886282dcc1b133d118470d40b0e3ef44a3622211a12a5af774a4ce22519199c1caea187597b1b7236699931929293e1b922155499090544ee88a854041f15351d07fea250618ca52e6930b5f9cc6797c0b4c11281e6282006f39833d8e30a91c9cc663af399d08ca634a749cd6a5af39ad28c00003b",
"47494638396193002000c41d00bebebe303338e3e3e3f3f3f3494d55cbcbcb556169dbdbdb696d755d697518191cf84800e72834ff8e79b2205dffd81c04559a0034694175a200498a004179d3d3d38e8e92757d8a9e9ea282868eb2b2b6000000ffffffffffff00000000000021ff0b584d502044617461584d503c3f787061636b657420626567696e3d22efbbbf222069643d2257354d304d7043656869487a7265537a4e54637a6b633964223f3e203c783a786d706d65746120786d6c6e733a783d2261646f62653a6e733a6d6574612f2220783a786d70746b3d2241646f626520584d5020436f726520352e302d633036302036312e3133343737372c20323031302f30322f31322d31373a33323a30302020202020202020223e203c7264663a52444620786d6c6e733a7264663d22687474703a2f2f7777772e77332e6f72672f313939392f30322f32322d7264662d73796e7461782d6e7323223e203c7264663a4465736372697074696f6e207264663a61626f75743d222220786d6c6e733a786d703d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f2220786d6c6e733a786d704d4d3d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f6d6d2f2220786d6c6e733a73745265663d22687474703a2f2f6e732e61646f62652e636f6d2f7861702f312e302f73547970652f5265736f75726365526566232220786d703a43726561746f72546f6f6c3d2241646f62652050686f746f73686f7020435335204d6163696e746f73682220786d704d4d3a496e7374616e636549443d22786d702e6969643a37324444313139354238383731314446383542344242443331333533313238322220786d704d4d3a446f63756d656e7449443d22786d702e6469643a3732444431313936423838373131444638354234424244333133353331323832223e203c786d704d4d3a4465726976656446726f6d2073745265663a696e7374616e636549443d22786d702e6969643a3732444431313933423838373131444638354234424244333133353331323832222073745265663a646f63756d656e7449443d22786d702e6469643a3732444431313934423838373131444638354234424244333133353331323832222f3e203c2f7264663a4465736372697074696f6e3e203c2f7264663a5244463e203c2f783a786d706d6574613e203c3f787061636b657420656e643d2272223f3e01fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201000021f9040100001d002c00000000930020000005ff60278ee4469ee869a62c19b470b7c6e94cab779da3f62efb25e0a8b723e68c37246da384318501459315084c53d62b4fbb158a0e06a1c2f202062e0a2882eb4ab0876ee1262c247012420380204460ca3e1764421919803b1617873918088b37761779774217027c4016078f3418159c311a05a0300000a42d041b9240061b08957342161ba82c18b5421ab94000bc3eaaac3eaec23b171b784086b629b8cc28bbcf27bed224c179ab50af75196999bf88e039d1adb417983906bb06e8370605afed34e71c0af23117c70240f91b15de39faf91ae68a43857b2d0cace1b06787015a02ce05e44040c31884292c71d8302860858dc78c15d818c72193031a30ffa670b50180059527f458d1704e020d09170610e8868000849b170a08789540da050d15e6b0390acfcab05528edd01040c155069752615480f00e194d9f1c60708090738f4203110688252b7457d109156270385a81165a0b34e68aa2051345060e1a0e58c0a03686850c1a3858007021435c1816266018998066a2c72c2a5c200ce00e8204eab462c0a04140624711f06a155477808133341807b570d0c7dfc08331b738ac61c0e2c61a0c27982ca0f20500a445738ea8218185e02d2a60e080c1b40047ce63542854b7c2eb622c0020989dd23660c1d26914eafdbb4006c303881baf8e0106e70100985f106c9fc381eaa515e55e0c8e3946db6b7d75e007ff79098ed0d8798b510743060320e61b6381bdc7820503fc27d47cf9b5309d0000e0a71f6eb7f8f79f7509103099862938a68181de0540002c302c58c0730400048325b709d6597d2c50e81e7b180a0523091c5620dd873461909f6a278c48a289471d85220ad31db062802ebe586405337687a00638a6e047060c2a404a58960010e4620248189608619556c091173225145e6185559d934f1617a5290200da81a0420970657e596a20297f8176d0a5970016172661f5dd19968c651e68e373efdd89a78218b0b9634a6e8661ea08030466ca9cf9d54918ac8989c2e76fba8ec46107f1c54aa87c879aa2985af149e7e8a311b129a906d3fd9a6c6098b2b869ff6fb7020b6aa8351260016d149230c09aaaf2680f02e19ed0dbb30c34d02e0316ecf911741d2446a6a40eb49baf03198c06c0bcf5e2471abefa32e00002df7a0258bdd2f53bdabbee3af0d0b79a2c8c54aaa36100b10301149241bcb18aa08105e816b27115c09149c28c0a21e080bb0d38e0660092a2300099b342586b05051406ac93ba5ac8eb9eff5680ac299e3849ec66483b89ec68192c5b627ee8aa23a926073c9daa97ff91a969c6f1f62c428508485ac88eddf2d69bb8061890c178abf648803a3ec37aef8c103e8794d863036d36875735e6afd3c022fd2c6986e69330e1f1a54a71bc015e6040638578a9b5c3fe466d633e82ec5918d91e5fe5d8ff6b012480d8dab0b68dc0ea34b15a05ea24a43ac26d8c553942aa30be5d2106c5bc571feeb15b621c0985fc9e0f93db0930f921c55b5a08f1720a6023f1fd8a40e4ec721ee48dc7d75b4a42a4e83c3fa1623ed2a0000215961f8302c2abbfbe2506b80f8302516f203f0bf46bef03fbe52132d7030bd8c102d0970100e660010fb840051260c0032610000668e00d10e8980048300614ac000202e8c0a3a4e90608980b077740c0114ef0280430e10953a2421a2c00310168210c5ea841202ce0021cf8605e2242080e2c2907ff0a001d76608a8334287648a9c6ec7c58893aedc03f2e014f0c02c090c6f8000089a90295625381ced8e88896221307aa609b7cd28c31108b39c0ab5aa000287e4b8a2c20001531f4c316e46724282bc00d3ad3c531966e8b22029af4a67783d309e0134714441a0b70bf1150f1002e792324ec80a119c5e60087e4c0770a00801874c6205e34807300c9254295e68b093a5d698c7803452ef2190cf1c2a264394b59aed107fb90a56e80a047148400003b"];

        private const _point:Point = new Point(0,0);
        private var _imAr:Vector.<uint>;//frames holder
        private var _imArL:uint;//total frames
        private var _bmd:BitmapData;//bitmapData reference
        private var _bmd2:BitmapData;//bitmapData reference for 2X
        private var _spd:uint;//animation delay in ms 
        private var _ti:uint;//animation inner time
        private var _im:int;//current animation frame counter
        private var _imW:uint;//width for subdivision
        private var _imH:uint;//height for subdivision
        private var _mode:Boolean = false;//loop or not
        private var _way:int = 1;//loop counter incrementer, loop mode dependent. Default:1
        private var _windowSpriteSheet:Window;
        private var _windowDisplayAnimation:Window;
        private var _windowDisplayAnimation2x:Window;
        private var _maxPreviewWindowW:uint = 330;
        private var _minPreviewWindowW:uint = 150;
        private var _maxPreviewWindowH:uint = 330;
        private var _minPreviewWindowH:uint = 120;
        private var _maxAnimWindowW:uint = 330;
        private var _minAnimWindowW:uint = 150;
        private var _maxAnimWindowH:uint = 330;
        private var _minAnimWindowH:uint = 150;
        private var _windowSetSource:Window;
        private var _windowSetSourceBg:ColorChooser;
        private var _windowSubDivisions:Window;
        private var _windowSubDivisionsBg:ColorChooser;
        private var _windowControlAnimation:Window;
        private var _windowControlAnimationBg:ColorChooser;        

        private var _sourceAvgColor:Bitmap = new Bitmap(new BitmapData(9,9,true,0xFFFFFFFF));
        private var _previewBitmap:Bitmap;
        private var _previewBgBitmap:Bitmap;
        private var _previewBgBitmapData:BitmapData;
        private var _previewGridBitmap:Bitmap;
        private var _previewGridBitmapData:BitmapData;
        private var _previewGridHighlightBitmap:Bitmap;
        private var _previewGridHighlightBitmapData:BitmapData;
        private var _scrollButtonLeft:PushButton;
        private var _scrollButtonRight:PushButton;

        private var _animationBitmap:Bitmap;
        private var _animationBitmapData:BitmapData;
        private var _animationBgBitmap:Bitmap;
        private var _animationBgBitmapData:BitmapData;
        private var _animationRect:Rectangle;
        private var _animationBitmap2:Bitmap;//2X size
        private var _animationBitmapData2:BitmapData;
        private var _animationBgBitmap2:Bitmap;
        private var _animationBgBitmapData2:BitmapData;
        private var _animationRect2:Rectangle;

        private var _sourceInfos:Text;
        private var _sourceName:Label;
        private var _subDivisionWidth:InputText;
        private var _subDivisionHeight:InputText;
        private var _width:uint;
        private var _height:uint;

        private var _animSpeedLabel:Label;
        private var _animFrameLabel:Label;
        private var _isGrid:CheckBox;
        private var _isLoop:CheckBox;
        private var _isScale2x:CheckBox;
        private var _slider:Slider;

        private var _loader:Loader;//required for samples demo only
        private var _assetsMemoryBank:Vector.<BitmapData> = new Vector.<BitmapData>;//required for samples demo only
        private var _assetsNum:uint = 0;//required for samples demo only
        private var _samplesCombo:ComboBox;//required for samples demo only

        public function ToolAnim () {
                buildWindowPreview();
                buildWindowDisplay();
                buildWindowDisplay2x();
                buildWindowSetSource();
                buildWindowSubDivisions();
                buildWindowControlAnimation();
                prepareAsset(0);//required for samples demo only
                prepareSamplesChoice();//required for samples demo only    
        }

        private function buildWindowPreview():void {
            _windowSpriteSheet = new Window(this,0,0,"Sprite Sheet preview");
            setProps(_windowSpriteSheet, {hasMinimizeButton:true,width:_minPreviewWindowW,height:_minPreviewWindowH});
        }

        private function scrollSpriteSheetLeft(e:Event):void {
            if (_imW == 0 || _imH == 0 || _previewBitmap.x == 0) {return;}
            _previewBitmap.x+=_imW;
            _previewBgBitmap.x+=_imW;
            _previewGridBitmap.x+=_imW;
        }

        private function scrollSpriteSheetRight(e:Event):void {
            if (_imW == 0 || _imH == 0 || _previewBitmap.x <= -(_width-_windowSpriteSheet.width)) {return;}
            _previewBitmap.x-=_imW;
            _previewBgBitmap.x-=_imW;
            _previewGridBitmap.x-=_imW;
        }

        private function buildWindowDisplay():void {
            _windowDisplayAnimation = new Window(this,0,_minPreviewWindowH+30,"Animation preview (1x)");
            setProps(_windowDisplayAnimation, {hasMinimizeButton:true,width:_minAnimWindowW,height:_minAnimWindowH});
        }

        private function buildWindowDisplay2x():void {
            _windowDisplayAnimation2x = new Window(this,_minPreviewWindowW+10,_minAnimWindowW+10,"Animation preview (2x)");
            setProps(_windowDisplayAnimation2x, {hasMinimizeButton:true,width:_minAnimWindowW,height:_minAnimWindowH});
        }

        private function buildWindowSetSource():void {
            _windowSetSource = new Window(this,_stageW-120,0,"Sprite Sheet source");
            setProps(_windowSetSource, {hasMinimizeButton:true,width:116,height:150});
            _sourceName = new Label(_windowSetSource.content,8,0,"No sprite sheet loaded.");
            new PushButton(_windowSetSource.content,8,18,"load sprite sheet",loadSpriteSheet);
            _sourceInfos = new Text(_windowSetSource.content,8,42,"");
            setProps(_sourceInfos, {width:100,height:50});
            setProps(_sourceAvgColor, {x:94,y:75});
            _windowSetSource.content.addChild(_sourceAvgColor);
            var _bgColorLabel:Label = new Label(_windowSetSource.content,6,92,"Sheet bg color");
            _windowSetSourceBg = new ColorChooser(_windowSetSource.content,8,110,0xFF00FF,setSpriteSheetBG);
            _windowSetSourceBg.usePopup = true;
        }
    
        private function setSpriteSheetBG(...rest):void {
            if(_width==0||_height==0||!_previewBgBitmapData){return;}
            _previewBgBitmapData.lock();
            _previewBgBitmapData.fillRect(new Rectangle(0,0,_width,_height),(255<<24) | _windowSetSourceBg.value);
            _previewBgBitmapData.unlock();
        }


        private function loadSpriteSheet(e:Event):void{
            var loadFile:LoadFile = new LoadFile();
            loadFile.atComplete = loadComplete;
            loadFile.start();
        }

        private function loadComplete(e:Event,fileName:String):void{
            initNewSpriteSheet(e.target.content,fileName);
        }

        private function initNewSpriteSheet(tgt:*,fileName:String):void {
            removeEventListener(Event.ENTER_FRAME,renderDisplay);
            var w:uint = tgt.width;
            var h:uint = tgt.height;
if ((w == h && w > 4095) || (w > 4095 && w < 8191 && h > 2048) || (h > 4095 && h < 8191 && w > 2048) || (w*h>16775168)){return;} //too big for flash 10
            _sourceName.text = fileName;
            _width = w;
            _height = h;
            _imW = _height;
            _imH = _height;
            _subDivisionHeight.text = String(_height);
            _subDivisionWidth.text = String(_height);
            _bmd = new BitmapData(_width,_height,true,0x00FFFFFF);
            _bmd.lock();
            _bmd.draw(tgt);
            _bmd.unlock();
            //we precompute the 2x zoom, but warning: size has to be compliant with flash10 capabilities
            _bmd2 =    new BitmapData(_width*2,_height*2,true,0x00FFFFFF);
            setScale2x();
            var a:* = _windowSpriteSheet.content;
            _previewBgBitmapData = new BitmapData(_width,_height,true,(255<<24) | _windowSetSourceBg.value);
            _previewBgBitmap = new Bitmap(_previewBgBitmapData);
            _previewBgBitmap.name = 'bg';
            if (a.getChildByName('bg')){var toGo:* = a.getChildByName('bg');a.removeChild(toGo);toGo= null;}
            a.addChild(_previewBgBitmap);
            _previewBitmap = new Bitmap(_bmd);
            _previewBitmap.name = 'bd';
            if (a.getChildByName('bd')){var toGo2:* = a.getChildByName('bd');a.removeChild(toGo2);toGo2= null;}
            a.addChild(_previewBitmap);
            _previewGridBitmapData = new BitmapData(_width+1,_height+1,true,0x00FFFFFF);
            _previewGridBitmap = new Bitmap(_previewGridBitmapData);
            _previewGridBitmap.name = 'grid';
            if (a.getChildByName('grid')){var toGo3:* = a.getChildByName('grid');a.removeChild(toGo3);toGo3= null;}
            a.addChild(_previewGridBitmap);
            setGrid();
            _previewGridHighlightBitmapData = new BitmapData(_width,_height,true,0x00FFFFFF);
            _previewGridHighlightBitmap = new Bitmap(_previewGridHighlightBitmapData);
            _previewGridHighlightBitmap.name = 'highlight';
            if (a.getChildByName('highlight')){var toGo6:* = a.getChildByName('highlight');a.removeChild(toGo6);toGo6= null;}
            a.addChild(_previewGridHighlightBitmap);      
            setProps(_windowSpriteSheet,{width:(_width>_maxPreviewWindowW?_maxPreviewWindowW:(_width<_minPreviewWindowW?_minPreviewWindowW:_width)),height:(_height>_maxPreviewWindowH?_maxPreviewWindowH+22:(_height<_minPreviewWindowH?_minPreviewWindowH+22:_height+22))});
            if (a.getChildByName('scrollLeft')){var toGo4:* = a.getChildByName('scrollLeft');a.removeChild(toGo4);toGo4= null;}
            _scrollButtonLeft = new PushButton(_windowSpriteSheet.content,0,_previewGridBitmap.y+_previewGridBitmap.height,"<<",scrollSpriteSheetLeft);
            setProps(_scrollButtonLeft, {name:'scrollLeft',width:50});
            if (a.getChildByName('scrollRight')){var toGo5:* = a.getChildByName('scrollRight');a.removeChild(toGo5);toGo4= null;}            
            _scrollButtonRight = new PushButton(_windowSpriteSheet.content,_scrollButtonLeft.width+_scrollButtonLeft.x+2,_scrollButtonLeft.y,">>",scrollSpriteSheetRight);
            setProps(_scrollButtonRight, {name:'scrollRight',width:50});
            
            var rgb:uint = getColorAverage(_bmd);
            _sourceInfos.text = "width: "+_width+"\nheight: "+_height+"\nave: "+"0x"+rgb.toString(16).toUpperCase();
            _sourceAvgColor.bitmapData.fillRect(new Rectangle(0,0,9,9),rgb); //avg color for png only
            _sourceAvgColor.alpha = (rgb >> 24 & 0xFF)/0xFF;
        }

        private function buildWindowSubDivisions():void {
            _windowSubDivisions = new Window(this,_stageW-120,155,"Subdivisions");
            setProps(_windowSubDivisions, {hasMinimizeButton:true,width:116,height:150});
            var _widthLabel:Label = new Label(_windowSubDivisions.content,6,4,"width");
            _subDivisionWidth = new InputText(_windowSubDivisions.content,8,22,String(_height),setGrid);
            setProps(_subDivisionWidth, {width:30,height:20,text:String(_height),maxChars:4,restrict:"0123456789"});
            var _heightLabel:Label = new Label(_windowSubDivisions.content,52,4,"height");
            _subDivisionHeight = new InputText(_windowSubDivisions.content,54,22,String(_height),setGrid);
            setProps(_subDivisionHeight, {width:30,height:20,maxChars:4,restrict:"0123456789"});
            var _gridColorLabel:Label = new Label(_windowSubDivisions.content,6,45,"Grid color");
            _windowSubDivisionsBg = new ColorChooser(_windowSubDivisions.content,8,63,0x00FF00,setGrid);
            _windowSubDivisionsBg.usePopup = true;
            _isGrid = new CheckBox(_windowSubDivisions.content,8,88,"Grid visible",setGrid);
            _isGrid.selected = true;
            var _subDivisionValidate:PushButton = new PushButton(_windowSubDivisions.content,8,105,"set and preview anim",setSubDivisions);
        }
        
        private function setHighlight(x:uint):void{
            var c:uint = (255<<24) | _windowSubDivisionsBg.value;
            var w:uint = uint(_subDivisionWidth.text);
            var h:uint = uint(_subDivisionHeight.text);
            if(w==0||h==0||!_previewGridBitmapData){return;}
            _previewGridHighlightBitmapData.lock();
            _previewGridHighlightBitmapData.fillRect(new Rectangle(0,0,_width,_height),0x00FFFFFF);
            _previewGridHighlightBitmapData.fillRect(new Rectangle(x*w,0,w,h),0x7700FF00);
            _previewGridHighlightBitmapData.unlock();
        }

        private function setGrid(...rest):void{
            var c:uint = (255<<24) | _windowSubDivisionsBg.value;
            var w:uint = uint(_subDivisionWidth.text);
            var h:uint = uint(_subDivisionHeight.text);
            if(w==0||h==0||!_previewGridBitmapData){return;}
            _previewGridBitmapData.lock();
            _previewGridBitmapData.fillRect(new Rectangle(0,0,_width+1,_height+1),0x00FFFFFF);
            if(_isGrid.selected) {
                for (var u:uint=0;u<_width;u+=w){
                    for (var j:uint=0;j<2;++j){
                        for (var i:uint=0;i<w;++i){
                            _previewGridBitmapData.setPixel32(i+u,j*h,c);
                        }
                        for (i=0;i<h;++i){
                            _previewGridBitmapData.setPixel32(j*w+u,i,c);
                        }
                    }
                }
            }
            _previewGridBitmapData.unlock();
        }

        private function setSubDivisions(...rest):void{
            if (uint(_subDivisionWidth.text) == 0 || uint(_subDivisionHeight.text) == 0) {return;}
            _imW = uint(_subDivisionWidth.text);
            _imH = uint(_subDivisionHeight.text);
            setGrid();
            initBuffer();
        }

        private function buildWindowControlAnimation():void {
            _windowControlAnimation = new Window(this,_stageW-120,310,"Animation Control");
            setProps(_windowControlAnimation, {hasMinimizeButton:true,width:116,height:150});
            var n:* = _windowControlAnimation.content;
            _slider = new Slider(Slider.HORIZONTAL,n,8,22,setFrameRate);
            setProps(_slider, {value:45,backClick:true});
            _animSpeedLabel = new Label(n,8,4,"animation delay: " + _slider.value*2 + "ms");    
            _animFrameLabel = new Label(n,8,30,"");
            _isLoop = new CheckBox(n,8,50,"Round Loop",setRoundLoop);
            _isLoop.selected = false;
            _isScale2x = new CheckBox(n,8,70,"Scale2x interpolation",setScale2x);
            _isScale2x.selected = false;
            var _animColorLabel:Label = new Label(n,6,85,"Anim bg color");
            _windowControlAnimationBg = new ColorChooser(n,8,103,0x00FFFF,setAnimationBG);
            _windowControlAnimationBg.usePopup = true;
            _windowControlAnimationBg.popupAlign = "top";
        }

        private function setAnimationBG(...rest):void {
            if(_imW==0||_imH==0||!_animationBgBitmapData){return;}
            _animationBgBitmapData.lock();
            _animationBgBitmapData.fillRect(new Rectangle(0,0,_imW,_imH),(255<<24) | _windowControlAnimationBg.value);
            _animationBgBitmapData.unlock();
            _animationBgBitmapData2.lock();
            _animationBgBitmapData2.fillRect(new Rectangle(0,0,_imW*2,_imH*2),(255<<24) | _windowControlAnimationBg.value);
            _animationBgBitmapData2.unlock();
        }

        private function setScale2x(...rest):void{
            var r:Rectangle = new Rectangle(0,0,_width*2,_height*2);
            if (_isScale2x.selected) {
                var tmpBmd2:BitmapData = scale2x(_bmd.clone());
                _bmd2.lock();
                _bmd2.fillRect(r,0x00FFFFFF);
                _bmd2.copyPixels(tmpBmd2,r,new Point(0,0),null,null,true);
                _bmd2.unlock();
            }
            else {
                var scaleMatrix:Matrix = new Matrix();
                scaleMatrix.scale(2,2);
                _bmd2.lock();
                _bmd2.draw(_bmd.clone(),scaleMatrix);
                _bmd2.unlock();
            }
        }
        
        private function setRoundLoop(e:Event):void{
            _mode = e.target.selected;
        }
        
        private function setFrameRate(e:Event):void{
            _spd = uint(e.target.value*2);
            _animSpeedLabel.text = "animation delay: " + uint(_slider.value*2) + "ms";
        }

        private function initBuffer(...rest):void{
            removeEventListener(Event.ENTER_FRAME,renderDisplay);
            var s:uint = Math.round(_width/_imW);
            _imAr = new Vector.<uint>;
            for (var i:uint=0;i<s;++i) {_imAr.push(i);}
            _imArL = _imAr.length;
            setProps(_windowDisplayAnimation, {width:(_imW>_maxAnimWindowW?_maxAnimWindowW:(_imW<_minAnimWindowW?_minAnimWindowW:_imW)),height:(_imH>_maxAnimWindowH?_maxAnimWindowH:(_imH<_minAnimWindowH?_minAnimWindowH:_imH+24))});
            setProps(_windowDisplayAnimation2x, {width:(_imW*2>_maxAnimWindowW?_maxAnimWindowW:(_imW*2<_minAnimWindowW?_minAnimWindowW:_imW*2)),height:(_imH*2>_maxAnimWindowH?_maxAnimWindowH:(_imH*2<_minAnimWindowH?_minAnimWindowH:_imH*2+24))});
            _spd = 90;
            _slider.value = uint(_spd/2);
            _animSpeedLabel.text = "animation delay: " + uint(_slider.value*2) + "ms";
            _ti = getTimer();
            _im = 0;
            var a:* = _windowDisplayAnimation.content;

            _animationBgBitmapData = new BitmapData(_imW,_imH,true,(255<<24) | _windowControlAnimationBg.value);
            _animationBgBitmap = new Bitmap(_animationBgBitmapData);
            setProps(_animationBgBitmap, {name:'bg',x:Math.round(a.parent.width/2 - _imW/2),y:2});
            if (a.getChildByName('bg')){var toGo:* = a.getChildByName('bg');a.removeChild(toGo); toGo = null;}
            a.addChild(_animationBgBitmap);

            _animationBitmapData = new BitmapData(_imW,_imH,true,0x00FFFFFF);
            _animationRect = new Rectangle(0,0,_imW,_imH);
            _animationBitmap = new Bitmap(_animationBitmapData);
            setProps(_animationBitmap, {name:'bd',x:Math.round(a.parent.width/2 - _imW/2),y:2});
            if (a.getChildByName('bd')){var toGo2:* = a.getChildByName('bd');a.removeChild(toGo2); toGo2 = null;}
            a.addChild(_animationBitmap);
            var b:* = _windowDisplayAnimation2x.content;
            _animationBgBitmapData2 = new BitmapData(_imW*2,_imH*2,true,(255<<24) | _windowControlAnimationBg.value);
            _animationBgBitmap2 = new Bitmap(_animationBgBitmapData2);
            setProps(_animationBgBitmap2, {name:'bg',x:Math.round(b.parent.width/2 - _imW),y:2});
            if (b.getChildByName('bg')){var toGo3:* = b.getChildByName('bg');b.removeChild(toGo3); toGo3 = null;}
            b.addChild(_animationBgBitmap2);
            _animationBitmapData2 = new BitmapData(_imW*2,_imH*2,true,0x00FFFFFF);
            _animationRect2 = new Rectangle(0,0,_imW*2,_imH*2);
            _animationBitmap2 = new Bitmap(_animationBitmapData2);
            setProps(_animationBitmap2, {name:'bd',x:Math.round(b.parent.width/2 - _imW),y:2});
            if (b.getChildByName('bd')){var toGo4:* = b.getChildByName('bd');b.removeChild(toGo4); toGo4 = null;}
            b.addChild(_animationBitmap2);
            addEventListener(Event.ENTER_FRAME,renderDisplay);
        }

        private function renderDisplay(e:Event):void {
            var t:uint = getTimer();
            if (t - _ti >=_spd){
                if (_mode == false) {
                    _im = (++_im)%_imArL;
                }
                else if (_mode == true) {
                    _im = (_im + _way);
                    if (_im == _imArL || _im < 0){_way = -_way; _im = (_im + _way*2);}
                }
                _ti = t; //update inner time
                _animationBitmapData.lock();//1x preview
                _animationBitmapData.fillRect(_animationRect,0x00FFFFFF);
                _animationBitmapData.copyPixels(_bmd,new Rectangle(_imAr[_im]*_imW,0,_imW,_imH),_point,null,null,true);
                _animationBitmapData.unlock();
                _animationBitmapData2.lock();//2x preview
                _animationBitmapData2.fillRect(_animationRect2,0x00FFFFFF);
                _animationBitmapData2.copyPixels(_bmd2,new Rectangle(_imAr[_im]*_imW<<1,0,_imW<<1,_imH<<1),_point,null,null,true);
                _animationBitmapData2.unlock();
                _animFrameLabel.text = "frame " + (_im+1);
                setHighlight(_im);
            }
        }
    
        private function getColorAverage(bitmapData:BitmapData):uint{
            var w:int = bitmapData.width;
            var h:int = bitmapData.height;
            var n:int = w*h;
            var a:uint;
            var r:uint;
            var g:uint;
            var b:uint;
            for (var i:uint=0;i<n;++i) {
                var argb:uint = bitmapData.getPixel32(i%w,Math.floor(i/w));
                a += argb >> 24 & 0xFF;
                r += argb >> 16 & 0xFF;
                g += argb >> 8 & 0xFF;
                b += argb & 0xFF;
            }
            a = Math.floor(a/n);
            r = Math.floor(r/n);
            g = Math.floor(g/n);
            b = Math.floor(b/n);
            return ((a*0x1000000+r*0x10000+g*0x100+b));
        }

        private function scale2x(b:BitmapData):BitmapData{
            var dest:BitmapData = new BitmapData(b.width*2,b.height*2,true,0x00FFFFFF);
            var E:uint,E0:uint,E1:uint,E2:uint,E3:uint,B:uint,D:uint,F:uint,H:uint,i:uint,j:uint,i2:uint,j2:uint;
            var w:uint = b.width;
            var h:uint = b.height;
            b.lock();
            dest.lock();
            for (i=0;i<w;++i){
                for (j=0;j<h;++j){
                    E = b.getPixel32(i,j);
                    if(i==0||j==0||i==w-1||j==h-1){E0=E1=E2=E3=E;}
                    else{                    
                        B = b.getPixel32(i,j-1);
                        D = b.getPixel32(i-1,j);
                        F = b.getPixel32(i+1,j);
                        H = b.getPixel32(i,j+1);
                        if (B!=H && D!=F){
                            E0 = (D == B)?D:E;
                            E1 = (B == F)?F:E;
                            E2 = (D == H)?D:E;
                            E3 = (H == F)?F:E;
                        }
                        else{E0=E1=E2=E3=E;}
                    }
                    i2 = i<<1;
                    j2 = j<<1;
                    dest.setPixel32(i2,j2,E0);
                    dest.setPixel32(i2+1,j2,E1);
                    dest.setPixel32(i2,j2+1,E2);
                    dest.setPixel32(i2+1,j2+1,E3);
                }
            }
            b.unlock();
            b.dispose();
            dest.unlock();
            return dest;
        }

        private function setProps(o:*,p:Object):void {
            for (var k:String in p) {o[k]=p[k];}
        }

        private function prepareAsset(n:int):void{
            var bytes:ByteArray = new ByteArray();
            var data1:Array=_samplesData[n].split("");
            var data2:Array=[];
            var d1l:int = data1.length;
            for (var i:int=0;i<d1l;i+=2){
                data2.push("0x"+data1[i]+data1[i+1]);
            }
            var d2l:int = data2.length;
            for (var j:int=0;j<d2l;++j){
                bytes[j] = data2[j];
            }
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,assetLoaded);
            _loader.loadBytes(bytes);
        }

        private function assetLoaded(event:Event):void {
            var t:BitmapData = new BitmapData(_loader.content.width,_loader.content.height,true,0x00FFFFFF);
            t.draw(_loader.content);
            _assetsMemoryBank.push(t);
            _assetsNum++;
            if (_assetsNum<_samplesData.length) {prepareAsset(_assetsNum);}
            else {viewSample(0);}
        }

        private function viewSample(n:uint):void {
            initNewSpriteSheet(_assetsMemoryBank[_previewSample[n][0]],_previewSample[n][1]);
            _subDivisionWidth.text = String(_previewSample[n][2]);
            setSubDivisions();
            _isScale2x.selected = _previewSample[n][3];
            setScale2x();
            _isLoop.selected = _previewSample[n][4];
            _mode = _isLoop.selected;
        }
        
        private function prepareSamplesChoice():void{
            var b:Array = [];
            for (var i:uint=0;i<_previewSample.length;++i) {
                b.push(_previewSample[i][1]);
            }
            _samplesCombo = new ComboBox(this,Math.round(_stageW/2)-120,_stageH-44,"Sprite Sheets Samples",b);
            setProps(_samplesCombo, {openPosition:'top', width:130,selectedIndex:0});
            var a:PushButton = new PushButton(this,Math.round(_stageW/2)-120,_stageH-22,"load sample",setSample);
            a.width = 130;
        }

        private function setSample(e:Event):void{
            viewSample(_samplesCombo.selectedIndex);
        }
        
    }
}

import flash.display.Loader;
import flash.events.Event;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.system.LoaderContext;
class LoadFile {
    private var _fileReference:FileReference;
    public var _name:String;
    public var atComplete:Function = function(e:Event,a:String):void{};

    public function start():void {
        if(_fileReference){return;}
        _fileReference = new FileReference();
        _fileReference.browse(getTypes());
        _fileReference.addEventListener(Event.SELECT,atSelect);
    }
    
    private function atSelect(e:Event):void{
        _fileReference.removeEventListener(Event.SELECT,atSelect);
        _fileReference.addEventListener(Event.COMPLETE,atFileComplete);
        _fileReference.load();
    }

    private function getTypes():Array {
        var allTypes:Array = new Array(getImageTypeFilter());
        return allTypes;
    }

    private function getImageTypeFilter():FileFilter {
        return new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png");
    }

    private function atFileComplete(e:Event):void{
        _fileReference.removeEventListener(Event.COMPLETE,atFileComplete);
        var loader:Loader = new Loader();
        _name = e.target.name;
        loader.loadBytes(e.target.data,new LoaderContext());
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE,atBytesComplete);
    }
    private function atBytesComplete(e:Event):void{
        e.target.removeEventListener(Event.COMPLETE,atBytesComplete);
        atComplete(e,_name);
    }
}