package bontos { /** * Завантажувач картинок в кілька потоків. * v.0.4*/ import flash.display.AVM1Movie; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.display.Loader; import flash.display.LoaderInfo; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IOErrorEvent; import flash.net.URLRequest; import flash.net.URLVariables; import flash.utils.Dictionary; import bontos.firebugTracer.Fbug; //import mx.core.FlexGlobals; //import spark.components.Application; public class BatchLoader { private var batchResources: Dictionary = new Dictionary(); private var loadersCount: int = 0; private var arrLoaders: Array = []; private var arrResourceAlias: Array = []; private var timeLoaded: Number = 0; private var parentListener: *; private var arrDuplicateAliases: Array = []; private var debugMode: Boolean = true; public function BatchLoader(pL: *) // constructor { parentListener = pL; addLoaders(); } /*********************************** PUBLIC FUNCTIONS **************************/ /** Задаємо кількість потоків для загрузки. * Потоки додаються негайно, а видаляютсья тільки після загрузки ними контенту. * Видалення потоків не працює (покищо) */ public function setCountChannels(numLoaders: int = 1): void { if(numLoaders >= 1){ if(numLoaders > loadersCount){ addLoaders(numLoaders - loadersCount); }else{ //removeLoader(numLoaders - loadersCount); } loadersCount = numLoaders; } } /** Починаєм грузити ресурси */ public function start(): void { timeLoaded = new Date().getTime(); for(var i: int = 0; i < loadersCount; i++){ loadNextResourse(arrLoaders[i] as Loader); } } public function add(resourceUrl: String, resourceAlias: String): void { if(!isDublicateKey(resourceAlias)){ resourceUrl = unescape(resourceUrl); batchResources[resourceAlias] = {url: resourceUrl, resource: null, loading: false}; arrResourceAlias.push(resourceAlias); if(debugMode) trace('added new URL == ', resourceAlias, ' - ', resourceUrl); }else{ arrDuplicateAliases.push(resourceAlias); } } public function get(resourceAlias: String, copy: Boolean = true): Object { var res: Object; if(batchResources[resourceAlias] != null){ if(copy){ if(batchResources[resourceAlias].resource is Bitmap){ var dispObj: DisplayObject = batchResources[resourceAlias].resource; var bmp:BitmapData = new BitmapData(dispObj.width, dispObj.height, true, 0x00FFFFFF); bmp.draw(dispObj); res = new Bitmap(bmp); }else{ res = batchResources[resourceAlias].resource; //для swf треба створюється ще один лоадер і віддається він, а не контен який він загрузив } }else{ res = batchResources[resourceAlias].resource; } }else{ trace('no res', resourceAlias); Fbug.warn('no resource ' + resourceAlias); parentListener.dispatchEvent(new BatchLoaderEvent(BatchLoaderEvent.NO_RESOURCE, false, false, resourceAlias)); } return res; } /*********************************** PRIVATE FUNCTIONS **************************/ private function loadNextResourse(ldrNext: Loader): void { var urlStr: String = getUrlForLoad(); if(urlStr != ''){ if(arrLoaders.length < 1) addLoaders(); var urlRequest: URLRequest = new URLRequest(urlStr); ldrNext.load(urlRequest); } } private function isDublicateKey(alias: String): Boolean { return batchResources[alias] != null; } private function getUrlForLoad(): String { var s: String = arrResourceAlias.shift(); if(s != null) batchResources[s].loading = true; s = s != null ? batchResources[s].url : ''; return s; } private function getAliasByUrl(resourceUrl: String): String { var resourceAlias: String = ''; //trace(resourceUrl, unescape(resourceUrl)); resourceUrl = unescape(resourceUrl); for (var key:String in batchResources) { var s: String = batchResources[key].url; while(s.indexOf('/') != -1){ s = s.substring(s.indexOf('/') + 1); } if(resourceUrl.indexOf(s) != -1){ resourceAlias = key; break; } } return resourceAlias; } private function addLoaders(numLoaders: int = 1): void { for(var i: int = 0; i < numLoaders; i++){ var ldr: Loader = new Loader(); ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onResourseLoaded); ldr.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); function ioErrorHandler(event:IOErrorEvent):void { trace("ioErrorHandler: " + event); //removeLoader(event.currentTarget as Loader); //addLoaders(); } arrLoaders.push(ldr); } loadersCount = arrLoaders.length; if(debugMode) trace('num loaders : ', arrLoaders.length); } private function removeLoader(ldr: Loader): void { for(var i: int = 0; i < arrLoaders.length; i++){ if(arrLoaders[i] == ldr){ //ldr = null; arrLoaders.splice(i, 1); break; } } } private function loadDuplicateUrl(urlLoadedImg: String, loadedContent: Bitmap): void { if(debugMode) trace('is duplicate '); urlLoadedImg = unescape(urlLoadedImg); for (var key: String in batchResources) { //if(batchResources[key].url == urlLoadedImg){ was if(urlLoadedImg.indexOf(batchResources[key].url) != -1){ batchResources[key].loading = false; var dispObj: DisplayObject = loadedContent; var bmp:BitmapData = new BitmapData(dispObj.width, dispObj.height, true, 0x00FFFFFF); bmp.draw(dispObj); batchResources[key].resource = new Bitmap(bmp); for(var i: int = 0; i < arrResourceAlias.length; i++){ if(arrResourceAlias[i] == key){ arrResourceAlias.splice(i, 1); i--; break; } } if(debugMode) trace('complete load'); parentListener.dispatchEvent(new BatchLoaderEvent(BatchLoaderEvent.COMPLETE_LOAD, false, false, key)); } } } /* private function loadDuplicateResource(duplicateAlias: String): void { for(var i: int = 0; i < arrDuplicateAliases.length; i++){ if(arrDuplicateAliases[i] == duplicateAlias){ parentListener.dispatchEvent(new BatchLoaderEvent(BatchLoaderEvent.COMPLETE_LOAD, false, false, duplicateAlias)); arrDuplicateAliases.splice(i, 1); i--; } } var loadedAll: Boolean = true; for (var key: String in batchResources) { if(batchResources[key].loading == true && batchResources[key].resource != null){ loadedAll = false; break; } } if(arrResourceAlias.length == 0 && loadedAll) parentListener.dispatchEvent(new BatchLoaderEvent(BatchLoaderEvent.COMPLETE_LOAD_ALL, false, false)); }*/ /*********************************** PRIVATE EVENT FUNCTIONS **************************/ private function onResourseLoaded(ev: Event): void { var ldrI: LoaderInfo = ev.currentTarget as LoaderInfo; var resourceAlias: String = getAliasByUrl(ldrI.url); //loadDuplicateResource(resourceAlias); var isLoadDuplicateUrl: Boolean = false; if(resourceAlias != ''){ if(ldrI.content is AVM1Movie){//AVM1Movie batchResources[resourceAlias].resource = ldrI.loader; removeLoader(ldrI.loader); addLoaders(); }else{ loadDuplicateUrl(ldrI.url, ldrI.content as Bitmap); isLoadDuplicateUrl = true; //batchResources[resourceAlias].resource = ldrI.content; } batchResources[resourceAlias].loading = false; } if(!isLoadDuplicateUrl){ if(debugMode) trace('complete load'); parentListener.dispatchEvent(new BatchLoaderEvent(BatchLoaderEvent.COMPLETE_LOAD, false, false, resourceAlias)); } var isAllLoaded: Boolean = arrResourceAlias.length == 0; if(isAllLoaded){ var loadedAll: Boolean = true; for (var key:String in batchResources) { if(batchResources[key].loading == true || batchResources[key].resource == null){ loadedAll = false; break; } } if(loadedAll && !loadedAllImagesOnce){ if(debugMode) trace(' time for load all resources: ', new Date().getTime() - timeLoaded + ' milliseconds'); //Alert.show(' time for load all resources: ' + (new Date().getTime() - timeLoaded) + ' milliseconds'); /** викликаєм подію про загрузку всіх ресурсів*/ parentListener.dispatchEvent( new BatchLoaderEvent( BatchLoaderEvent.COMPLETE_LOAD_ALL, false, false)); loadedAllImagesOnce = true; } }else if(arrLoaders.length <= loadersCount){ removeLoader(ldrI.loader); //нашо оце???? loadNextResourse(ldrI.loader); } } private var loadedAllImagesOnce: Boolean = false; } }