mirror of
https://github.com/MapMakersAndProgrammers/alternativa3d-archive.git
synced 2025-10-27 18:29:07 -07:00
273 lines
10 KiB
ActionScript
273 lines
10 KiB
ActionScript
package alternativa.engine3d.loaders {
|
||
import alternativa.engine3d.loaders.events.BatchTextureLoaderErrorEvent;
|
||
import alternativa.engine3d.loaders.events.LoaderEvent;
|
||
import alternativa.engine3d.loaders.events.LoaderProgressEvent;
|
||
|
||
import flash.display.BitmapData;
|
||
import flash.events.ErrorEvent;
|
||
import flash.events.Event;
|
||
import flash.events.EventDispatcher;
|
||
import flash.events.IOErrorEvent;
|
||
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 alternativa.engine3d.loaders.events.BatchTextureLoaderErrorEvent.LOADER_ERROR
|
||
*/
|
||
[Event (name="loaderError", type="alternativa.engine3d.loaders.events.BatchTextureLoaderErrorEvent")]
|
||
/**
|
||
* Событие посылается, когда начинается загрузка очередной текстуры.
|
||
*
|
||
* @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")]
|
||
|
||
/**
|
||
* @private
|
||
* Пакетный загрузчик текстур.
|
||
*
|
||
* При возникновении ошибки во время загрузки очередной текстуры, пакетный загрузчик заменяет соответствующую текстуру изображением-заглушкой и
|
||
* генерирует событие ошибки пакетного загрузчика. Пользователь пакетного загрузчика в обработчике ошибки может решить, прерывать ли процесс
|
||
* загрузки вызовом метода close() или нет.
|
||
*/
|
||
public class BatchTextureLoader extends EventDispatcher {
|
||
/**
|
||
* Текстура-заглушка для замены незагруженных текстур.
|
||
*/
|
||
private static var stubBitmapData:BitmapData;
|
||
|
||
private static const IDLE:int = 0;
|
||
private static const LOADING:int = 1;
|
||
|
||
// Состояние загрузчика
|
||
private var state:int = IDLE;
|
||
|
||
// Загрузчик текстур
|
||
private var textureLoader:TextureLoader;
|
||
// Контекст безопасности загрузчика
|
||
private var loaderContext:LoaderContext;
|
||
// Базовый URL файлов текстур
|
||
private var baseURL:String;
|
||
// Пакет с описанием текстур материалов (textureName => TextureInfo)
|
||
private var batch:Object;
|
||
// Список имён текстур в пакете
|
||
private var textureNames:Vector.<String>;
|
||
// Индекс текущего материала.
|
||
private var textureIndex:int;
|
||
// Общее количество загружаемых текстур
|
||
private var numTextures:int;
|
||
// Результирующая таблица (textureName => BitmapData)
|
||
private var _textures:Object;
|
||
|
||
/**
|
||
* Создаёт новый экземпляр загрузчика.
|
||
*/
|
||
public function BatchTextureLoader() {
|
||
}
|
||
|
||
/**
|
||
* Результирующая таблица битмапов. Ключами являются имена текстур, значениями -- объекты класса BitmapData.
|
||
*/
|
||
public function get textures():Object {
|
||
return _textures;
|
||
}
|
||
|
||
/**
|
||
* Прекращает текущую загрузку.
|
||
*/
|
||
public function close():void {
|
||
if (state == LOADING) {
|
||
textureLoader.close();
|
||
cleanup();
|
||
_textures = null;
|
||
state = IDLE;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Очищает ссылку на загруженный список текстур материалов.
|
||
*/
|
||
public function unload():void {
|
||
_textures = null;
|
||
}
|
||
|
||
/**
|
||
* Запускает загрузку.
|
||
*
|
||
* @param baseURL базовый URL файлов текстур
|
||
* @param batch описание пакета текстур -- таблица textureName => TextureInfo
|
||
* @param loaderContext LoaderContext для загрузки
|
||
*/
|
||
public function load(baseURL:String, batch:Object, loaderContext:LoaderContext = null):void {
|
||
if (baseURL == null) {
|
||
throw ArgumentError("Parameter baseURL cannot be null");
|
||
}
|
||
if (batch == null) {
|
||
throw ArgumentError("Parameter batch cannot be null");
|
||
}
|
||
|
||
this.baseURL = baseURL;
|
||
this.batch = batch;
|
||
this.loaderContext = loaderContext;
|
||
|
||
if (textureLoader == null) {
|
||
textureLoader = new TextureLoader();
|
||
} else {
|
||
close();
|
||
}
|
||
textureLoader.addEventListener(Event.OPEN, onTextureLoadingStart);
|
||
textureLoader.addEventListener(LoaderProgressEvent.LOADER_PROGRESS, onProgress);
|
||
textureLoader.addEventListener(Event.COMPLETE, onTextureLoadingComplete);
|
||
textureLoader.addEventListener(IOErrorEvent.IO_ERROR, onLoadingError);
|
||
|
||
// Получение массива имён текстур
|
||
textureNames = new Vector.<String>();
|
||
for (var textureName:String in batch) {
|
||
textureNames.push(textureName);
|
||
}
|
||
numTextures = textureNames.length;
|
||
// Старт загрузки
|
||
textureIndex = 0;
|
||
_textures = {};
|
||
|
||
if (hasEventListener(Event.OPEN)) {
|
||
dispatchEvent(new Event(Event.OPEN));
|
||
}
|
||
|
||
state = LOADING;
|
||
loadNextTexture();
|
||
}
|
||
|
||
/**
|
||
* Запускает загрузку очередной текстуры.
|
||
*/
|
||
private function loadNextTexture():void {
|
||
var info:TextureInfo = batch[textureNames[textureIndex]];
|
||
var opacityMapFileUrl:String = info.opacityMapFileName == null || info.opacityMapFileName == "" ? null : baseURL + info.opacityMapFileName;
|
||
textureLoader.load(baseURL + info.diffuseMapFileName, opacityMapFileUrl, loaderContext);
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function onTextureLoadingStart(e:Event):void {
|
||
if (hasEventListener(LoaderEvent.PART_OPEN)) {
|
||
dispatchEvent(new LoaderEvent(LoaderEvent.PART_OPEN, numTextures, textureIndex));
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function onProgress(e:LoaderProgressEvent):void {
|
||
if (hasEventListener(LoaderProgressEvent.LOADER_PROGRESS)) {
|
||
var totalProgress:Number = (textureIndex + e.totalProgress)/numTextures;
|
||
dispatchEvent(new LoaderProgressEvent(LoaderProgressEvent.LOADER_PROGRESS, numTextures, textureIndex, totalProgress, e.bytesLoaded, e.bytesTotal));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обрабатывает завершение загрузки текстуры.
|
||
*/
|
||
private function onTextureLoadingComplete(e:Event):void {
|
||
_textures[textureNames[textureIndex]] = textureLoader.bitmapData;
|
||
tryNextTexure();
|
||
}
|
||
|
||
/**
|
||
* Обрабатывает ошибку при загрузке текстуры. Незагруженная текстура заменяется изображением-заглушкой и
|
||
* генерируется событие ошибки пакетного загрузчика.
|
||
*/
|
||
private function onLoadingError(e:ErrorEvent):void {
|
||
var textureName:String = textureNames[textureIndex];
|
||
_textures[textureName] = getStubBitmapData();
|
||
dispatchEvent(new BatchTextureLoaderErrorEvent(BatchTextureLoaderErrorEvent.LOADER_ERROR, textureName, e.text));
|
||
tryNextTexure();
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function tryNextTexure():void {
|
||
// Проверка состояния необходима, т.к. оно могло измениться в результате вызова метода close() в обработчике события ошибки загрузки
|
||
if (state == IDLE) return;
|
||
|
||
if (hasEventListener(LoaderEvent.PART_COMPLETE)) {
|
||
dispatchEvent(new LoaderEvent(LoaderEvent.PART_COMPLETE, numTextures, textureIndex));
|
||
}
|
||
if (++textureIndex == numTextures) {
|
||
// Загружены все текстуры, отправляется сообщение о завершении
|
||
cleanup();
|
||
removeEventListeners();
|
||
state = IDLE;
|
||
if (hasEventListener(Event.COMPLETE)) {
|
||
dispatchEvent(new Event(Event.COMPLETE));
|
||
}
|
||
} else {
|
||
loadNextTexture();
|
||
}
|
||
}
|
||
|
||
/**
|
||
*
|
||
*/
|
||
private function removeEventListeners():void {
|
||
textureLoader.removeEventListener(Event.OPEN, onTextureLoadingStart);
|
||
textureLoader.removeEventListener(LoaderProgressEvent.LOADER_PROGRESS, onProgress);
|
||
textureLoader.removeEventListener(Event.COMPLETE, onTextureLoadingComplete);
|
||
textureLoader.removeEventListener(IOErrorEvent.IO_ERROR, onLoadingError);
|
||
}
|
||
|
||
/**
|
||
* Очищает внутренние ссылки на объекты.
|
||
*/
|
||
private function cleanup():void {
|
||
loaderContext = null;
|
||
textureNames = null;
|
||
}
|
||
|
||
/**
|
||
* Метод для получения текстуры-заглушки.
|
||
*
|
||
* @return текстура-заглушка для замещения незагруженных текстур
|
||
*/
|
||
private function getStubBitmapData():BitmapData {
|
||
if (stubBitmapData == null) {
|
||
var size:uint = 20;
|
||
stubBitmapData = new BitmapData(size, size, false, 0);
|
||
for (var i:uint = 0; i < size; i++) {
|
||
for (var j:uint = 0; j < size; j += 2) {
|
||
stubBitmapData.setPixel((i%2) ? j : (j + 1), i, 0xFF00FF);
|
||
}
|
||
}
|
||
}
|
||
return stubBitmapData;
|
||
}
|
||
|
||
}
|
||
} |