package away3d.loaders
{
import away3d.containers.*;
import away3d.arcane;
import away3d.core.base.*;
import away3d.core.draw.*;
import away3d.core.render.*;
import away3d.core.utils.*;
import away3d.events.*;
import away3d.loaders.data.*;
import away3d.loaders.utils.*;
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.utils.getTimer;
use namespace arcane;
/**
* Dispatched when the 3d object loader completes a file load successfully.
*
* @eventType away3d.events.LoaderEvent
*/
[Event(name="loadSuccess",type="away3d.events.LoaderEvent")]
/**
* Dispatched when the 3d object loader fails to load a file.
*
* @eventType away3d.events.LoaderEvent
*/
[Event(name="loadError",type="away3d.events.LoaderEvent")]
/**
* Abstract loader class used as a placeholder for loading 3d content
*/
public class Object3DLoader extends ObjectContainer3D
{
/** @private */
arcane static function loadGeometry(url:String, Parser:Class, binary:Boolean, init:Object):Object3DLoader
{
var ini:Init = Init.parse(init);
var loaderClass:Class = ini.getObject("loader") as Class || CubeLoader;
var loader:Object3DLoader = new loaderClass(ini);
loader.startLoadingGeometry(url, Parser, binary);
return loader;
}
/** @private */
arcane static function parseGeometry(data:*, Parser:Class, init:Object):Object3DLoader
{
var ini:Init = Init.parse(init);
var loaderClass:Class = ini.getObject("loader") as Class || CubeLoader;
var loader:Object3DLoader = new loaderClass(ini);
loader.startParsingGeometry(data, Parser);
return loader;
}
private var _broadcaster:Sprite = new Sprite();
private var Parser:Class;
public var parser:AbstractParser;
private var _parseStart:int;
private var _parseTime:int;
private var result:Object3D;
private var urlloader:URLLoader;
private var _child:Object3D;
private var _materialData:MaterialData;
private var _loadQueue:TextureLoadQueue;
private var _loadsuccess:LoaderEvent;
private var _loaderror:LoaderEvent;
private var _zipsourcesloaded:LoaderEvent;
private function registerURL(object:Object3D):void
{
if (object is ObjectContainer3D) {
for each (_child in (object as ObjectContainer3D).children)
registerURL(_child);
} else if (object is Mesh) {
(object as Mesh).url = url;
}
}
private function startLoadingGeometry(url:String, Parser:Class, binary:Boolean):void
{
mode = LOADING_GEOMETRY;
this.Parser = Parser;
this.url = url;
urlloader = new URLLoader();
urlloader.dataFormat = binary ? URLLoaderDataFormat.BINARY : URLLoaderDataFormat.TEXT;
urlloader.addEventListener(IOErrorEvent.IO_ERROR, onGeometryError);
urlloader.addEventListener(ProgressEvent.PROGRESS, onGeometryProgress);
urlloader.addEventListener(Event.COMPLETE, onGeometryComplete);
urlloader.load(new URLRequest(url));
}
private function startParsingGeometry(data:*, Parser:Class):void
{
_broadcaster.addEventListener(Event.ENTER_FRAME, update);
mode = PARSING_GEOMETRY;
_parseStart = getTimer();
this.Parser = Parser;
this.parser = new Parser(data, ini);
parser.addEventListener(ParserEvent.PARSE_SUCCESS, onParserComplete, false, 0, true);
parser.addEventListener(ParserEvent.PARSE_ERROR, onParserError, false, 0, true);
parser.addEventListener(ParserEvent.PARSE_PROGRESS, onParserProgress, false, 0, true);
parser.parseNext();
}
private function startLoadingTextures():void
{
mode = LOADING_TEXTURES;
_loadQueue = new TextureLoadQueue();
for each (_materialData in materialLibrary)
{
if (_materialData.materialType == MaterialData.TEXTURE_MATERIAL && !_materialData.material)
{
var req:URLRequest = new URLRequest(materialLibrary.texturePath + _materialData.textureFileName);
var loader:TextureLoader = new TextureLoader();
_loadQueue.addItem(loader, req);
}
}
_loadQueue.addEventListener(IOErrorEvent.IO_ERROR, onTextureError);
_loadQueue.addEventListener(ProgressEvent.PROGRESS, onTextureProgress);
_loadQueue.addEventListener(Event.COMPLETE, onTextureComplete);
_loadQueue.start();
}
private function update(event:Event):void
{
parser.parseNext();
}
protected function notifySuccess(event:Event):void
{
mode = COMPLETE;
ini.addForCheck();
result.transform.multiply(result.transform, transform);
result.name = name;
result.ownCanvas = ownCanvas;
result.filters = filters;
result.visible = visible;
result.mouseEnabled = mouseEnabled;
result.useHandCursor = useHandCursor;
result.alpha = alpha;
result.pushback = pushback;
result.pushfront = pushfront;
result.pivotPoint.clone(pivotPoint);
result.extra = (extra is IClonable) ? (extra as IClonable).clone() : extra;
if (parent != null) {
result.parent = parent;
parent = null;
}
//register url with hierarchy
registerURL(result);
//dispatch event
if (!_loadsuccess)
_loadsuccess = new LoaderEvent(LoaderEvent.LOAD_SUCCESS, this);
dispatchEvent(_loadsuccess);
}
protected function notifyError(event:Event):void
{
mode = ERROR;
//dispatch event
if (!_loaderror)
_loaderror = new LoaderEvent(LoaderEvent.LOAD_ERROR, this);
dispatchEvent(_loaderror);
}
protected function notifyProgress(event:Event):void
{
}
/**
* Automatically fired on an geometry error event.
*
* @see away3d.loaders.utils.TextureLoadQueue
*/
protected function onGeometryError(event:IOErrorEvent):void
{
notifyError(event);
}
/**
* Automatically fired on a geometry progress event
*/
protected function onGeometryProgress(event:ProgressEvent):void
{
notifyProgress(event);
dispatchEvent(event);
}
/**
* Automatically fired on a geometry complete event
*/
protected function onGeometryComplete(event:Event):void
{
startParsingGeometry(urlloader.data, Parser);
}
/**
* Automatically fired on an parser error event.
*
* @see away3d.loaders.utils.TextureLoadQueue
*/
protected function onParserError(event:ParserEvent):void
{
_broadcaster.removeEventListener(Event.ENTER_FRAME, update);
notifyError(event);
}
/**
* Automatically fired on a parser progress event
*/
protected function onParserProgress(event:ParserEvent):void
{
notifyProgress(event);
_parseTime = getTimer() - _parseStart;
if (_parseTime < parseTimeout) {
parser.parseNext();
}else {
dispatchEvent(event);
_parseStart = getTimer();
}
}
/**
* Automatically fired on a parser complete event
*/
protected function onParserComplete(event:ParserEvent):void
{
_broadcaster.removeEventListener(Event.ENTER_FRAME, update);
result = event.result;
materialLibrary = result.materialLibrary;
if (materialLibrary && materialLibrary.autoLoadTextures && materialLibrary.loadRequired) {
texturePath = materialLibrary.texturePath;
startLoadingTextures();
} else {
notifySuccess(event);
}
}
/**
* Automatically fired on an texture error event.
*
* @see away3d.loaders.utils.TextureLoadQueue
*/
protected function onTextureError(event:IOErrorEvent):void
{
notifyError(event);
}
/**
* Automatically fired on a texture progress event
*/
protected function onTextureProgress(event:ProgressEvent):void
{
notifyProgress(event);
dispatchEvent(event);
}
/**
* Automatically fired on a texture complete event
*/
protected function onTextureComplete(event:Event):void
{
materialLibrary.texturesLoaded(_loadQueue);
notifySuccess(event);
}
/**
* Constant value string representing the geometry loading mode of the 3d object loader.
*/
public const LOADING_GEOMETRY:String = "loading_geometry";
/**
* Constant value string representing the geometry parsing mode of the 3d object loader.
*/
public const PARSING_GEOMETRY:String = "parsing_geometry";
/**
* Constant value string representing the texture loading mode of the 3d object loader.
*/
public const LOADING_TEXTURES:String = "loading_textures";
/**
* Constant value string representing a completed loader mode.
*/
public const COMPLETE:String = "complete";
/**
* Constant value string representing a problem loader mode.
*/
public const ERROR:String = "error";
/**
* Returns the current loading mode of the 3d object loader.
*/
public var mode:String;
/**
* Returns the the data container being used by the loaded file.
*/
public var containerData:ContainerData;
/**
* Returns the filepath to the directory where any required texture files are located.
*/
public var texturePath:String;
/**
* Returns the url string of the file being loaded.
*/
public var url:String;
/**
* Defines a timeout period for file parsing (in milliseconds).
*/
public var parseTimeout:int;
/**
* Returns a 3d object relating to the currently visible model.
* While a file is being loaded, this takes the form of the 3d object loader placeholder.
* The default placeholder is CubeLoader
*
* Once the file has been loaded and is ready to view, the handle returns the
* parsed 3d object file and the placeholder object is swapped in the scenegraph tree.
*
* @see away3d.loaders.CubeLoader
*/
public function get handle():Object3D
{
return result || this;
}
/**
* Creates a new Object3DLoader object.
* Not intended for direct use, use the static parse or load methods found on the file loader classes.
*
* @param init [optional] An initialisation object for specifying default instance properties.
*/
public function Object3DLoader(init:Object = null)
{
super(init);
parseTimeout = ini.getNumber("parseTimeout", 40000);
ini.removeFromCheck();
}
/**
* Default method for adding a loadsuccess event listener
*
* @param listener The listener function
*/
public function addOnSuccess(listener:Function):void
{
addEventListener(LoaderEvent.LOAD_SUCCESS, listener, false, 0, true);
}
/**
* Default method for removing a loadsuccess event listener
*
* @param listener The listener function
*/
public function removeOnSuccess(listener:Function):void
{
removeEventListener(LoaderEvent.LOAD_SUCCESS, listener, false);
}
/**
* Default method for adding a loaderror event listener
*
* @param listener The listener function
*/
public function addOnError(listener:Function):void
{
addEventListener(LoaderEvent.LOAD_ERROR, listener, false, 0, true);
}
/**
* Default method for removing a loaderror event listener
*
* @param listener The listener function
*/
public function removeOnError(listener:Function):void
{
removeEventListener(LoaderEvent.LOAD_ERROR, listener, false);
}
}
}