/ruhlamat_website/o3djs/io.js
JavaScript | 577 lines | 233 code | 36 blank | 308 comment | 48 complexity | a8c61ea1c44b59eed8c301c0fe7b8dd6 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
- /*
- * Copyright 2009, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
- /**
- * @fileoverview This file contains various functions and class for io.
- */
-
- o3djs.provide('o3djs.io');
-
- /**
- * A Module with various io functions and classes.
- * @namespace
- */
- o3djs.io = o3djs.io || {};
-
- /**
- * Creates a LoadInfo object.
- * @param {(!o3d.ArchiveRequest|!o3d.FileRequest|!XMLHttpRequest)} opt_request
- * The request to watch.
- * @param {boolean} opt_hasStatus true if opt_request is a
- * o3d.ArchiveRequest vs for example an o3d.FileRequest or an
- * XMLHttpRequest.
- * @return {!o3djs.io.LoadInfo} The new LoadInfo.
- * @see o3djs.io.LoadInfo
- */
- o3djs.io.createLoadInfo = function(opt_request, opt_hasStatus) {
- return new o3djs.io.LoadInfo(opt_request, opt_hasStatus);
- };
-
- /**
- * A class to help with progress reporting for most loading utilities.
- *
- * Example:
- * <pre>
- * var g_loadInfo = null;
- * g_id = window.setInterval(statusUpdate, 500);
- * g_loadInfo = o3djs.scene.loadScene(client, pack, parent,
- * 'http://google.com/somescene.o3dtgz',
- * callback);
- *
- * function callback(pack, parent, exception) {
- * g_loadInfo = null;
- * window.clearInterval(g_id);
- * if (!exception) {
- * // do something with scene just loaded
- * }
- * }
- *
- * function statusUpdate() {
- * if (g_loadInfo) {
- * var progress = g_loadInfo.getKnownProgressInfoSoFar();
- * document.getElementById('loadstatus').innerHTML = progress.percent;
- * }
- * }
- * </pre>
- *
- * @constructor
- * @param {(!o3d.ArchiveRequest|!o3d.FileRequest|!XMLHttpRequest)} opt_request
- * The request to watch.
- * @param {boolean} opt_hasStatus true if opt_request is a
- * o3d.ArchiveRequest vs for example an o3d.FileRequest or an
- * XMLHttpRequest.
- * @see o3djs.scene.loadScene
- * @see o3djs.io.loadArchive
- * @see o3djs.io.loadTexture
- * @see o3djs.loader.Loader
- */
- o3djs.io.LoadInfo = function(opt_request, opt_hasStatus) {
- this.request_ = opt_request;
- this.hasStatus_ = opt_hasStatus;
- this.streamLength_ = 0; // because the request may have been freed.
- this.children_ = [];
- };
-
- /**
- * Adds another LoadInfo as a child of this LoadInfo so they can be
- * managed as a group.
- * @param {!o3djs.io.LoadInfo} loadInfo The child LoadInfo.
- */
- o3djs.io.LoadInfo.prototype.addChild = function(loadInfo) {
- this.children_.push(loadInfo);
- };
-
- /**
- * Marks this LoadInfo as finished.
- */
- o3djs.io.LoadInfo.prototype.finish = function() {
- if (this.request_) {
- if (this.hasStatus_) {
- this.streamLength_ = this.request_.streamLength;
- }
- this.request_ = null;
- }
- };
-
- /**
- * Gets the total bytes that will be streamed known so far.
- * If you are only streaming 1 file then this will be the info for that file but
- * if you have queued up many files using an o3djs.loader.Loader only a couple of
- * files are streamed at a time meaning that the size is not known for files
- * that have yet started to download.
- *
- * If you are downloading many files for your application and you want to
- * provide a progress status you have about 4 options
- *
- * 1) Use LoadInfo.getTotalBytesDownloaded() /
- * LoadInfo.getTotalKnownBytesToStreamSoFar() and just be aware the bar will
- * grown and then shrink as new files start to download and their lengths
- * become known.
- *
- * 2) Use LoadInfo.getTotalRequestsDownloaded() /
- * LoadInfo.getTotalKnownRequestsToStreamSoFar() and be aware the granularity
- * is not all that great since it only reports fully downloaded files. If you
- * are downloading a bunch of small files this might be ok.
- *
- * 3) Put all your files in one archive. Then there will be only one file and
- * method 1 will work well.
- *
- * 4) Figure out the total size in bytes of the files you will download and put
- * that number in your application, then use LoadInfo.getTotalBytesDownloaded()
- * / MY_APPS_TOTAL_BYTES_TO_DOWNLOAD.
- *
- * @return {number} The total number of currently known bytes to be streamed.
- */
- o3djs.io.LoadInfo.prototype.getTotalKnownBytesToStreamSoFar = function() {
- if (!this.streamLength_ && this.request_ && this.hasStatus_) {
- this.streamLength_ = this.request_.streamLength;
- }
- var total = this.streamLength_;
- for (var cc = 0; cc < this.children_.length; ++cc) {
- total += this.children_[cc].getTotalKnownBytesToStreamSoFar();
- }
- return total;
- };
-
- /**
- * Gets the total bytes downloaded so far.
- * @return {number} The total number of currently known bytes to be streamed.
- */
- o3djs.io.LoadInfo.prototype.getTotalBytesDownloaded = function() {
- var total = (this.request_ && this.hasStatus_) ?
- this.request_.bytesReceived : this.streamLength_;
- for (var cc = 0; cc < this.children_.length; ++cc) {
- total += this.children_[cc].getTotalBytesDownloaded();
- }
- return total;
- };
-
- /**
- * Gets the total streams that will be download known so far.
- * We can't know all the streams since you could use an o3djs.loader.Loader
- * object, request some streams, then call this function, then request some
- * more.
- *
- * See LoadInfo.getTotalKnownBytesToStreamSoFar for details.
- * @return {number} The total number of requests currently known to be streamed.
- * @see o3djs.io.LoadInfo.getTotalKnownBytesToStreamSoFar
- */
- o3djs.io.LoadInfo.prototype.getTotalKnownRequestsToStreamSoFar = function() {
- var total = 1;
- for (var cc = 0; cc < this.children_.length; ++cc) {
- total += this.children_[cc].getTotalKnownRequestToStreamSoFar();
- }
- return total;
- };
-
- /**
- * Gets the total requests downloaded so far.
- * @return {number} The total requests downloaded so far.
- */
- o3djs.io.LoadInfo.prototype.getTotalRequestsDownloaded = function() {
- var total = this.request_ ? 0 : 1;
- for (var cc = 0; cc < this.children_.length; ++cc) {
- total += this.children_[cc].getTotalRequestsDownloaded();
- }
- return total;
- };
-
- /**
- * Gets progress info.
- * This is commonly formatted version of the information available from a
- * LoadInfo.
- *
- * See LoadInfo.getTotalKnownBytesToStreamSoFar for details.
- * @return {{percent: number, downloaded: string, totalBytes: string,
- * base: number, suffix: string}} progress info.
- * @see o3djs.io.LoadInfo.getTotalKnownBytesToStreamSoFar
- */
- o3djs.io.LoadInfo.prototype.getKnownProgressInfoSoFar = function() {
- var percent = 0;
- var bytesToDownload = this.getTotalKnownBytesToStreamSoFar();
- var bytesDownloaded = this.getTotalBytesDownloaded();
- if (bytesToDownload > 0) {
- percent = Math.floor(bytesDownloaded / bytesToDownload * 100);
- }
-
- var base = (bytesToDownload < 1024 * 1024) ? 1024 : (1024 * 1024);
-
- return {
- percent: percent,
- downloaded: (bytesDownloaded / base).toFixed(2),
- totalBytes: (bytesToDownload / base).toFixed(2),
- base: base,
- suffix: (base == 1024 ? 'kb' : 'mb')}
-
- };
-
- /**
- * Loads text from an external file. This function is synchronous.
- * @param {string} url The url of the external file.
- * @return {string} the loaded text if the request is synchronous.
- */
- o3djs.io.loadTextFileSynchronous = function(url) {
- o3djs.BROWSER_ONLY = true;
-
- var error = 'loadTextFileSynchronous failed to load url "' + url + '"';
- var request;
- if (!o3djs.base.IsMSIE() && window.XMLHttpRequest) {
- request = new XMLHttpRequest();
- if (request.overrideMimeType) {
- request.overrideMimeType('text/plain');
- }
- } else if (window.ActiveXObject) {
- request = new ActiveXObject('MSXML2.XMLHTTP.3.0');
- } else {
- throw 'XMLHttpRequest is disabled';
- }
- request.open('GET', url, false);
- request.send(null);
- if (request.readyState != 4) {
- throw error;
- }
- return request.responseText;
- };
-
- /**
- * Loads text from an external file. This function is asynchronous.
- * @param {string} url The url of the external file.
- * @param {function(string, *): void} callback A callback passed the loaded
- * string and an exception which will be null on success.
- * @return {!o3djs.io.LoadInfo} A LoadInfo to track progress.
- */
- o3djs.io.loadTextFile = function(url, callback) {
- o3djs.BROWSER_ONLY = true;
-
- var error = 'loadTextFile failed to load url "' + url + '"';
- var request;
- if (!o3djs.base.IsMSIE() && window.XMLHttpRequest) {
- request = new XMLHttpRequest();
- if (request.overrideMimeType) {
- request.overrideMimeType('text/plain');
- }
- } else if (window.ActiveXObject) {
- request = new ActiveXObject('MSXML2.XMLHTTP.3.0');
- } else {
- throw 'XMLHttpRequest is disabled';
- }
- var loadInfo = o3djs.io.createLoadInfo(request, false);
- request.open('GET', url, true);
- var finish = function() {
- if (request.readyState == 4) {
- var text = '';
- // HTTP reports success with a 200 status. The file protocol reports
- // success with zero. HTTP does not use zero as a status code (they
- // start at 100).
- // https://developer.mozilla.org/En/Using_XMLHttpRequest
- var success = request.status == 200 || request.status == 0;
- if (success) {
- text = request.responseText;
- }
- loadInfo.finish();
- callback(text, success ? null : 'could not load: ' + url);
- }
- };
- request.onreadystatechange = finish;
- request.send(null);
- return loadInfo;
- };
-
- /**
- * A ArchiveInfo object loads and manages an archive of files.
- * There are methods for locating a file by uri and for freeing
- * the archive.
- *
- * You can only read archives that have as their first file a file named
- * 'aaaaaaaa.o3d' the contents of the which is 'o3d'. This is to prevent O3D
- * from being used to read arbitrary tar gz files.
- *
- * Example:
- * <pre>
- * var loadInfo = o3djs.io.loadArchive(pack,
- * 'http://google.com/files.o3dtgz',
- * callback);
- *
- * function callback(archiveInfo, exception) {
- * if (!exception) {
- * pack.createTextureFromRawData(
- * archiveInfo.getFileByURI('logo.jpg'), true);
- * pack.createTextureFromRawData(
- * archiveInfo.getFileByURI('wood/oak.png'), true);
- * pack.createTextureFromRawData(
- * archiveInfo.getFileByURI('wood/maple.dds'), true);
- * archiveInfo.destroy();
- * } else {
- * alert(exception);
- * }
- * }
- * </pre>
- *
- * @constructor
- * @param {!o3d.Pack} pack Pack to create request in.
- * @param {string} url The url of the archive file.
- * @param {!function(!o3djs.io.ArchiveInfo, *): void} onFinished A
- * callback that is called when the archive is finished loading and passed
- * the ArchiveInfo and an exception which is null on success.
- */
- o3djs.io.ArchiveInfo = function(pack, url, onFinished) {
- var that = this;
-
- /**
- * The list of files in the archive by uri.
- * @type {!Object}
- */
- this.files = {};
-
- /**
- * The pack used to create the archive request.
- * @type {!o3d.Pack}
- */
- this.pack = pack;
-
- /**
- * True if this archive has not be destroyed.
- * @type {boolean}
- */
- this.destroyed = false;
-
- this.request_ = null;
-
- /**
- * Records each RawData file as it comes in.
- * @private
- * @param {!o3d.RawData} rawData RawData from archive request.
- */
- function addFile(rawData) {
- that.files[rawData.uri] = rawData;
- }
-
- /**
- * The LoadInfo to track loading progress.
- * @type {!o3djs.io.LoadInfo}
- */
- this.loadInfo = o3djs.io.loadArchiveAdvanced(
- pack,
- url,
- addFile,
- function(request, exception) {
- that.request_ = request;
- onFinished(that, exception);
- });
- };
-
- /**
- * Releases all the RAW data associated with this archive. It does not release
- * any objects created from that RAW data.
- */
- o3djs.io.ArchiveInfo.prototype.destroy = function() {
- if (!this.destroyed) {
- this.pack.removeObject(this.request_);
- this.destroyed = true;
- this.files = {};
- }
- };
-
- /**
- * Gets files by regular expression or wildcards from the archive.
- * @param {(string|!RegExp)} uri of file to get. Can have wildcards '*' and '?'.
- * @param {boolean} opt_caseInsensitive Only valid if it's a wildcard string.
- * @return {!Array.<!o3d.RawData>} An array of the matching RawDatas for
- * the files matching or undefined if it doesn't exist.
- */
- o3djs.io.ArchiveInfo.prototype.getFiles = function(uri,
- opt_caseInsensitive) {
- if (!(uri instanceof RegExp)) {
- uri = uri.replace(/(\W)/g, '\\$&');
- uri = uri.replace(/\\\*/g, '.*');
- uri = uri.replace(/\\\?/g, '.');
- uri = new RegExp(uri, opt_caseInsensitive ? 'i' : '');
- }
- var files = [];
- for (var key in this.files) {
- if (uri.test(key)) {
- files.push(this.files[key]);
- }
- }
-
- return files;
- };
-
- /**
- * Gets a file by URI from the archive.
- * @param {string} uri of file to get.
- * @param {boolean} opt_caseInsensitive True to be case insensitive. Default
- * false.
- * @return {(o3d.RawData|undefined)} The RawData for the file or undefined if
- * it doesn't exist.
- */
- o3djs.io.ArchiveInfo.prototype.getFileByURI = function(
- uri,
- opt_caseInsensitive) {
- if (opt_caseInsensitive) {
- uri = uri.toLowerCase();
- for (var key in this.files) {
- if (key.toLowerCase() == uri) {
- return this.files[key];
- }
- }
- return undefined;
- } else {
- return this.files[uri];
- }
- };
-
- /**
- * Loads an archive file.
- * When the entire archive is ready the onFinished callback will be called
- * with an ArchiveInfo for accessing the archive.
- *
- * @param {!o3d.Pack} pack Pack to create request in.
- * @param {string} url The url of the archive file.
- * @param {!function(!o3djs.io.ArchiveInfo, *): void} onFinished A
- * callback that is called when the archive is successfully loaded and an
- * Exception object which is null on success.
- * @return {!o3djs.io.LoadInfo} The a LoadInfo for tracking progress.
- * @see o3djs.io.ArchiveInfo
- */
- o3djs.io.loadArchive = function(pack,
- url,
- onFinished) {
- var archiveInfo = new o3djs.io.ArchiveInfo(pack, url, onFinished);
- return archiveInfo.loadInfo;
- };
-
- /**
- * Loads an archive file. This function is asynchronous. This is a low level
- * version of o3djs.io.loadArchive which can be used for things like
- * progressive loading.
- *
- * @param {!o3d.Pack} pack Pack to create request in.
- * @param {string} url The url of the archive file.
- * @param {!function(!o3d.RawData): void} onFileAvailable A callback, taking a
- * single argument 'data'. As each file is loaded from the archive, this
- * function is called with the file's data.
- * @param {!function(!o3d.ArchiveRequest, *): void} onFinished
- * A callback that is called when the archive is successfully loaded. It is
- * passed the ArchiveRquest and null on success or a javascript exception on
- * failure.
- * @return {!o3djs.io.LoadInfo} A LoadInfo for tracking progress.
- */
- o3djs.io.loadArchiveAdvanced = function(pack,
- url,
- onFileAvailable,
- onFinished) {
- var error = 'loadArchive failed to load url "' + url + '"';
- var request = pack.createArchiveRequest();
- var loadInfo = o3djs.io.createLoadInfo(request, true);
- request.open('GET', url);
- request.onfileavailable = function() {
- onFileAvailable(/** @type {!o3d.RawData} */ (request.data));
- };
- /**
- * @ignore
- */
- request.onreadystatechange = function() {
- if (request.done) {
- loadInfo.finish();
- var success = request.success;
- var exception = null;
- if (!success) {
- exception = request.error;
- if (!exception) {
- exception = 'unknown error loading archive';
- }
- }
- onFinished(request, exception);
- }
- };
- request.send();
- return loadInfo;
- };
-
- /**
- * Loads a texture.
- *
- * Textures are loaded asynchronously.
- *
- * Example:
- * <pre>
- * var loadInfo = o3djs.io.loadTexture(pack,
- * 'http://google.com/someimage.jpg',
- * callback);
- *
- * function callback(texture, exception) {
- * if (!exception) {
- * g_mySampler.texture = texture;
- * } else {
- * alert(exception);
- * }
- * }
- * </pre>
- *
- *
- * @param {!o3d.Pack} pack Pack to load texture into.
- * @param {string} url URL of texture to load.
- * @param {!function(o3d.Texture, *): void} callback Callback when
- * texture is loaded. It will be passed the texture and an exception on
- * error or null on success.
- * @return {!o3djs.io.LoadInfo} A LoadInfo to track progress.
- * @see o3djs.io.createLoader
- */
- o3djs.io.loadTexture = function(pack, url, callback) {
- // TODO: change this to get use RawData and Bitmap
- var request = pack.createFileRequest('TEXTURE');
- var loadInfo = o3djs.io.createLoadInfo(
- /** @type {!o3d.FileRequest} */ (request),
- false);
- request.open('GET', url, true);
- /**
- * @ignore
- */
- request.onreadystatechange = function() {
- if (request.done) {
- var texture = request.texture;
- var success = request.success;
- var exception = request.error;
- loadInfo.finish();
- pack.removeObject(request);
- if (!success && !exception) {
- exception = 'unknown error loading texture';
- }
- callback(texture, success ? null : exception);
- }
- };
- request.send();
- return loadInfo;
- };
-
-