mirror of
https://github.com/MapMakersAndProgrammers/alternativa3d-archive.git
synced 2025-10-27 18:29:07 -07:00
268 lines
9.4 KiB
ActionScript
268 lines
9.4 KiB
ActionScript
package alternativa.engine3d.loaders {
|
||
import alternativa.engine3d.loaders.events.LoaderEvent;
|
||
import alternativa.engine3d.loaders.events.LoaderProgressEvent;
|
||
|
||
import flash.display.Bitmap;
|
||
import flash.display.BitmapData;
|
||
import flash.display.BitmapDataChannel;
|
||
import flash.display.BlendMode;
|
||
import flash.display.Loader;
|
||
import flash.display.LoaderInfo;
|
||
import flash.events.Event;
|
||
import flash.events.EventDispatcher;
|
||
import flash.events.IOErrorEvent;
|
||
import flash.events.ProgressEvent;
|
||
import flash.geom.Matrix;
|
||
import flash.geom.Point;
|
||
import flash.net.URLRequest;
|
||
import flash.system.LoaderContext;
|
||
|
||
/**
|
||
* Событие посылается, когда начинается загрузка ресурса.
|
||
*
|
||
* @eventType flash.events.Event.OPEN
|
||
*/
|
||
[Event (name="open", type="flash.events.Event")]
|
||
/**
|
||
* Событие посылается, когда загрузка ресурса успешно завершена.
|
||
*
|
||
* @eventType flash.events.Event.COMPLETE
|
||
*/
|
||
[Event (name="complete", type="flash.events.Event")]
|
||
/**
|
||
* Событие посылается при возникновении ошибки загрузки.
|
||
*
|
||
* @eventType flash.events.IOErrorEvent.IO_ERROR
|
||
*/
|
||
[Event (name="ioError", type="flash.events.IOErrorEvent")]
|
||
/**
|
||
* Событие посылается, когда начинается загрузка очередной части ресурса.
|
||
*
|
||
* @eventType alternativa.engine3d.loaders.events.LoaderEvent.PART_OPEN
|
||
*/
|
||
[Event (name="partOpen", type="alternativa.engine3d.loaders.events.LoaderEvent")]
|
||
/**
|
||
* Событие посылается, когда загрузка очередной части ресурса успешно завершена.
|
||
*
|
||
* @eventType alternativa.engine3d.loaders.events.LoaderEvent.PART_COMPLETE
|
||
*/
|
||
[Event (name="partComplete", type="alternativa.engine3d.loaders.events.LoaderEvent")]
|
||
/**
|
||
* Событие посылается для отображения прогресса загрузки.
|
||
*
|
||
* @eventType alternativa.engine3d.loaders.events.LoaderProgressEvent.LOADER_PROGRESS
|
||
*/
|
||
[Event (name="loaderProgress", type="alternativa.engine3d.loaders.events.LoaderProgressEvent")]
|
||
|
||
/**
|
||
* Загрузчик текстуры, состоящей из одного или двух файлов. В случае, если указан второй файл, он используется для заполнения альфа-канала
|
||
* получаемой текстуры.
|
||
*/
|
||
public class TextureLoader extends EventDispatcher {
|
||
|
||
private static const IDLE:int = -1;
|
||
private static const LOADING_DIFFUSE_MAP:int = 0;
|
||
private static const LOADING_ALPHA_MAP:int = 1;
|
||
|
||
private var state:int = IDLE;
|
||
private var bitmapLoader:Loader;
|
||
private var loaderContext:LoaderContext;
|
||
private var alphaTextureUrl:String;
|
||
private var _bitmapData:BitmapData;
|
||
|
||
/**
|
||
* Создаёт новый экземпляр. Если указан URL диффузной части текстуры, то сразу начинается загрузка.
|
||
*
|
||
* @param diffuseTextureUrl URL диффузной части текстуры
|
||
* @param alphaTextureUrl URL карты прозрачности
|
||
* @param loaderContext LoaderContext, используемый при загрузке
|
||
*/
|
||
public function TextureLoader() {
|
||
}
|
||
|
||
/**
|
||
* Загруженная текстура.
|
||
*/
|
||
public function get bitmapData():BitmapData {
|
||
return _bitmapData;
|
||
}
|
||
|
||
/**
|
||
* Загрузка текстурных карт. При успешной загрузке посылается сообщение <code>Event.COMPLETE</code>.
|
||
*
|
||
* @param diffuseTextureUrl URL файла диффузной карты
|
||
* @param alphaTextureUrl URL файла карты прозрачности
|
||
* @param loaderContext LoaderContext, используемый при загрузке
|
||
*/
|
||
public function load(diffuseTextureUrl:String, alphaTextureUrl:String = null, loaderContext:LoaderContext = null):void {
|
||
unload();
|
||
this.alphaTextureUrl = alphaTextureUrl == "" ? null : alphaTextureUrl;
|
||
this.loaderContext = loaderContext;
|
||
|
||
loadPart(LOADING_DIFFUSE_MAP, diffuseTextureUrl);
|
||
}
|
||
|
||
/**
|
||
* Прекращвет текущую загрузку. Если нет активных загрузок, не происходит ничего.
|
||
*/
|
||
public function close():void {
|
||
if (state == IDLE) return;
|
||
state = IDLE;
|
||
bitmapLoader.unload();
|
||
destroyLoader();
|
||
alphaTextureUrl = null;
|
||
loaderContext = null;
|
||
}
|
||
|
||
/**
|
||
* Очищает внутренние ссылки на загруженные объекты, чтобы сборщик мусора смог их удалить.
|
||
*/
|
||
public function unload():void {
|
||
close();
|
||
_bitmapData = null;
|
||
}
|
||
|
||
/**
|
||
* Очищает временные внутренние ссылки.
|
||
*/
|
||
private function cleanup():void {
|
||
destroyLoader();
|
||
alphaTextureUrl = null;
|
||
loaderContext = null;
|
||
}
|
||
|
||
/**
|
||
* Запускает загрузку части текстуры.
|
||
*
|
||
* @param state фаза загрузки
|
||
* @param url URL загружаемого файла
|
||
*/
|
||
private function loadPart(state:int, url:String):void {
|
||
this.state = state;
|
||
createLoader();
|
||
bitmapLoader.load(new URLRequest(url), loaderContext);
|
||
}
|
||
|
||
/**
|
||
* Обрабатывает начало загрузки очередной части текстуры.
|
||
*/
|
||
private function onPartLoadingOpen(e:Event):void {
|
||
if (_bitmapData == null && hasEventListener(Event.OPEN)) {
|
||
dispatchEvent(new Event(Event.OPEN));
|
||
}
|
||
if (hasEventListener(LoaderEvent.PART_OPEN)) {
|
||
dispatchEvent(new LoaderEvent(LoaderEvent.PART_OPEN, 2, state == LOADING_DIFFUSE_MAP ? 0 : 1));
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function onPartLoadingProgress(e:ProgressEvent):void {
|
||
if (hasEventListener(LoaderProgressEvent.LOADER_PROGRESS)) {
|
||
var partNumber:int = state == LOADING_DIFFUSE_MAP ? 0 : 1;
|
||
var totalProgress:Number = 0.5*(partNumber + e.bytesLoaded/e.bytesTotal);
|
||
dispatchEvent(new LoaderProgressEvent(LoaderProgressEvent.LOADER_PROGRESS, 2, partNumber, totalProgress, e.bytesLoaded, e.bytesTotal));
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function onPartLoadingComplete(e:Event):void {
|
||
switch (state) {
|
||
case LOADING_DIFFUSE_MAP: {
|
||
// Загрузилась диффузная текстура. При необходимости загружается карта прозрачности.
|
||
_bitmapData = Bitmap(bitmapLoader.content).bitmapData;
|
||
destroyLoader();
|
||
dispatchPartComplete(0);
|
||
if (alphaTextureUrl != null) {
|
||
loadPart(LOADING_ALPHA_MAP, alphaTextureUrl);
|
||
} else {
|
||
complete();
|
||
}
|
||
break;
|
||
}
|
||
case LOADING_ALPHA_MAP: {
|
||
// Загрузилась карта прозрачности. Выполняется копирование прозрачности в альфа-канал диффузной текстуры.
|
||
var pt:Point = new Point();
|
||
var tmpBmd:BitmapData = _bitmapData;
|
||
_bitmapData = new BitmapData(_bitmapData.width, _bitmapData.height);
|
||
_bitmapData.copyPixels(tmpBmd, tmpBmd.rect, pt);
|
||
|
||
var alpha:BitmapData = Bitmap(bitmapLoader.content).bitmapData;
|
||
destroyLoader();
|
||
if (_bitmapData.width != alpha.width || _bitmapData.height != alpha.height) {
|
||
tmpBmd.draw(alpha, new Matrix(_bitmapData.width/alpha.width, 0, 0, _bitmapData.height/alpha.height), null, BlendMode.NORMAL, null, true);
|
||
alpha.dispose();
|
||
alpha = tmpBmd;
|
||
} else {
|
||
tmpBmd.dispose();
|
||
}
|
||
_bitmapData.copyChannel(alpha, alpha.rect, pt, BitmapDataChannel.RED, BitmapDataChannel.ALPHA);
|
||
alpha.dispose();
|
||
dispatchPartComplete(1);
|
||
complete();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Создаёт событие завершения загрузки части текстуры.
|
||
*
|
||
* @param partnNumber номер загруженной части текстуры
|
||
*/
|
||
private function dispatchPartComplete(partNumber:int):void {
|
||
if (hasEventListener(LoaderEvent.PART_COMPLETE)) {
|
||
dispatchEvent(new LoaderEvent(LoaderEvent.PART_COMPLETE, 2, partNumber));
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function onLoadError(e:Event):void {
|
||
state = IDLE;
|
||
cleanup();
|
||
dispatchEvent(e);
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function complete():void {
|
||
state = IDLE;
|
||
cleanup();
|
||
if (hasEventListener(Event.COMPLETE)) {
|
||
dispatchEvent(new Event(Event.COMPLETE));
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function createLoader():void {
|
||
bitmapLoader = new Loader();
|
||
var loaderInfo:LoaderInfo = bitmapLoader.contentLoaderInfo;
|
||
loaderInfo.addEventListener(Event.OPEN, onPartLoadingOpen);
|
||
loaderInfo.addEventListener(ProgressEvent.PROGRESS, onPartLoadingProgress);
|
||
loaderInfo.addEventListener(Event.COMPLETE, onPartLoadingComplete);
|
||
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function destroyLoader():void {
|
||
if (bitmapLoader == null) return;
|
||
bitmapLoader.unload();
|
||
var loaderInfo:LoaderInfo = bitmapLoader.contentLoaderInfo;
|
||
loaderInfo.removeEventListener(Event.OPEN, onPartLoadingOpen);
|
||
loaderInfo.removeEventListener(ProgressEvent.PROGRESS, onPartLoadingProgress);
|
||
loaderInfo.removeEventListener(Event.COMPLETE, onPartLoadingComplete);
|
||
loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
|
||
bitmapLoader = null;
|
||
}
|
||
}
|
||
} |