@awayjs/core
Version:
AwayJS core classes
291 lines (290 loc) • 11.3 kB
JavaScript
import { __extends } from "tslib";
import { AbstractMethodError } from '../errors/AbstractMethodError';
import { AssetEvent } from '../events/AssetEvent';
import { EventDispatcher } from '../events/EventDispatcher';
import { ParserEvent } from '../events/ParserEvent';
import { ParserUtils } from '../parsers/ParserUtils';
import { ResourceDependency } from '../parsers/ResourceDependency';
import { getTimer } from '../utils/getTimer';
import { RequestAnimationFrame } from '../utils/RequestAnimationFrame';
/**
* <code>ParserBase</code> provides an abstract base export class for objects
* that convert blocks of data to data structures supported by away.
*
* If used by <code>Loader</code> to automatically determine the parser type,
* two public static methods should be implemented, with the following
* signatures:
*
* <code>public static supportsType(extension : string) : boolean</code>
* Indicates whether or not a given file extension is supported by the parser.
*
* <code>public static supportsData(data : *) : boolean</code> Tests whether a
* data block can be parsed by the parser.
*
* Furthermore, for any concrete subtype, the method <code>initHandle</code>
* should be overridden to immediately create the object that will contain the
* parsed data. This allows <code>ResourceManager</code> to return an object
* handle regardless of whether the object was loaded or not.
*
* @see Loader
*/
var ParserBase = /** @class */ (function (_super) {
__extends(ParserBase, _super);
/**
* Creates a new ParserBase object
* @param format The data format of the file data to be parsed. Can be
* either <code>ParserDataFormat.BINARY</code> or
* <code>ParserDataFormat.PLAIN_TEXT</code>, and should be provided by the
* concrete subtype.
*
* @see away.loading.parsers.ParserDataFormat
*/
function ParserBase(format) {
var _this = _super.call(this) || this;
_this.materialMode = 0;
_this._dataFormat = format;
_this._dependencies = new Array();
_this._onIntervalDelegate = function (event) { return _this._onInterval(event); };
_this._timer = new RequestAnimationFrame(_this._onIntervalDelegate, _this);
return _this;
}
//------------------------------------------------------------------------------------------------------------------
// TODO: add error checking for the following ( could cause a problem if
// this function is not implemented )
//------------------------------------------------------------------------------------------------------------------
// Needs to be implemented in all Parsers (<code>public static
//supportsType(extension : string) : boolean</code>
//* Indicates whether or not a given file extension is supported by the
// parser.
// ----------------------------------------------------------------------------------------------------------------
ParserBase.supportsType = function (extension) {
throw new AbstractMethodError();
};
Object.defineProperty(ParserBase.prototype, "content", {
get: function () {
return this._content;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ParserBase.prototype, "parsingFailure", {
get: function () {
return this._parsingFailure;
},
set: function (b) {
this._parsingFailure = b;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ParserBase.prototype, "parsingPaused", {
get: function () {
return this._parsingPaused;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ParserBase.prototype, "parsingComplete", {
get: function () {
return this._parsingComplete;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ParserBase.prototype, "data", {
get: function () {
return this._data;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ParserBase.prototype, "dataFormat", {
/**
* The data format of the file data to be parsed. Options are
* <code>URLLoaderDataFormat.BINARY</code>,
* <code>URLLoaderDataFormat.ARRAY_BUFFER</code>,
* <code>URLLoaderDataFormat.BLOB</code>,
* <code>URLLoaderDataFormat.VARIABLES</code> or
* <code>URLLoaderDataFormat.TEXT</code>.
*/
get: function () {
return this._dataFormat;
},
enumerable: false,
configurable: true
});
/**
* Parse data (possibly containing bytearry, plain text or BitmapAsset)
* asynchronously, meaning that the parser will periodically stop parsing so
* that the AVM may proceed to the next frame.
*
* @param data The untyped data object in which the loaded data resides.
* @param frameLimit number of milliseconds of parsing allowed per frame.
* The actual time spent on a frame can exceed this number since time-checks
* can only be performed between logical sections of the parsing procedure.
*/
ParserBase.prototype.parseAsync = function (data, frameLimit) {
if (frameLimit === void 0) { frameLimit = 30; }
this._data = data;
this.startParsing(frameLimit);
};
Object.defineProperty(ParserBase.prototype, "dependencies", {
// public parseSync(data: any): IAsset {
// this._data = data;
// let state = ParserBase.MORE_TO_PARSE;
// while (state == ParserBase.MORE_TO_PARSE) {
// state = this._pProceedParsing();
// }
// return this._pContent;
// }
/**
* A list of dependencies that need to be loaded and resolved for the object
* being parsed.
*/
get: function () {
return this._dependencies;
},
enumerable: false,
configurable: true
});
/**
* Resolve a dependency when it's loaded. For example, a dependency
* containing an ImageResource would be assigned to a Mesh instance as a
* BitmapMaterial, a scene graph object would be added to its intended
* parent. The dependency should be a member of the dependencies property.
*
* @param resourceDependency The dependency to be resolved.
*/
ParserBase.prototype.resolveDependency = function (resourceDependency) {
throw new AbstractMethodError();
};
/**
* Resolve a dependency loading failure. Used by parser to eventually
* provide a default map
*
* @param resourceDependency The dependency to be resolved.
*/
ParserBase.prototype.resolveDependencyFailure = function (resourceDependency) {
throw new AbstractMethodError();
};
/**
* Resolve a dependency name
*
* @param resourceDependency The dependency to be resolved.
*/
ParserBase.prototype.resolveDependencyName = function (resourceDependency, asset) {
return asset.name;
};
ParserBase.prototype.resumeParsing = function () {
this._parsingPaused = false;
//get started!
if (this.hasTime())
this.proceedParsing();
};
ParserBase.prototype.finalizeAsset = function (asset, name) {
if (name === void 0) { name = null; }
// If the asset has no name, give it a per-type default name.
asset.name = name || asset.name || asset.assetType;
this.dispatchEvent(new AssetEvent(AssetEvent.ASSET_COMPLETE, asset));
};
/**
* Parse the next block of data.
* @return Whether or not more data needs to be parsed. Can be
* <code>ParserBase.ParserBase.PARSING_DONE</code> or
* <code>ParserBase.ParserBase.MORE_TO_PARSE</code>.
*/
ParserBase.prototype.proceedParsing = function () {
throw new AbstractMethodError();
};
ParserBase.prototype.dieWithError = function (message) {
if (message === void 0) { message = 'Unknown parsing error'; }
this._parsingFailure = true;
this.dispatchEvent(new ParserEvent(ParserEvent.PARSE_ERROR, message));
};
ParserBase.prototype.addDependency = function (id, req, parser, data, retrieveAsRawData, suppressErrorEvents, sub_id) {
if (parser === void 0) { parser = null; }
if (data === void 0) { data = null; }
if (retrieveAsRawData === void 0) { retrieveAsRawData = false; }
if (suppressErrorEvents === void 0) { suppressErrorEvents = false; }
if (sub_id === void 0) { sub_id = 0; }
var dependency = new ResourceDependency(id, req, data, parser, this, retrieveAsRawData, suppressErrorEvents, sub_id);
this._dependencies.push(dependency);
return dependency;
};
ParserBase.prototype.pauseAndRetrieveDependencies = function () {
this._parsingPaused = true;
this.dispatchEvent(new ParserEvent(ParserEvent.READY_FOR_DEPENDENCIES));
};
/**
* Tests whether or not there is still time left for parsing within the
* maximum allowed time frame per session.
* @return True if there is still time left, false if the maximum allotted
* time was exceeded and parsing should be interrupted.
*/
ParserBase.prototype.hasTime = function () {
this._isParsing = ((getTimer() - ParserBase._lastFrameTime) < this._frameLimit);
//If parsing has stopped due to framelimit, start RAF and wait for next animation frame
if (!this._isParsing)
this._timer.start();
return this._isParsing;
};
/**
* Called when the parsing pause interval has passed and parsing can
* proceed.
*/
ParserBase.prototype._onInterval = function (event) {
if (event === void 0) { event = null; }
ParserBase._lastFrameTime = getTimer();
this._isParsing = true;
//stop RAF to continue parsing
this._timer.stop();
this.proceedParsing();
};
/**#
* Initializes the parsing of data.
* @param frameLimit The maximum duration of a parsing session.
*/
ParserBase.prototype.startParsing = function (frameLimit) {
this._frameLimit = frameLimit;
//get started!
if (this.hasTime())
this.proceedParsing();
};
/**
* Finish parsing the data.
*/
ParserBase.prototype.finishParsing = function () {
if (this._parsingFailure)
return;
this._parsingComplete = true;
this._isParsing = false;
this.dispatchEvent(new ParserEvent(ParserEvent.PARSE_COMPLETE));
};
/**
*
* @returns {string}
* @private
*/
ParserBase.prototype.getTextData = function () {
return ParserUtils.toString(this._data);
};
/**
*
* @returns {ByteArray}
* @private
*/
ParserBase.prototype.getByteData = function () {
return ParserUtils.toByteArray(this._data);
};
/**
*
* @returns {any}
* @private
*/
ParserBase.prototype.getData = function () {
return this._data;
};
ParserBase._lastFrameTime = 0;
return ParserBase;
}(EventDispatcher));
export { ParserBase };