summaryrefslogtreecommitdiffstats
path: root/o3d/samples/o3djs/serialization.js
diff options
context:
space:
mode:
authorgspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-27 23:15:42 +0000
committergspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-27 23:15:42 +0000
commit05b47f7a8c5451f858dc220df0e3a97542edace6 (patch)
treea2273d619f0625c9d44d40842845ccce2eac1045 /o3d/samples/o3djs/serialization.js
parent5cdc8bdb4c847cefe7f4542bd10c9880c2c557a0 (diff)
downloadchromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.zip
chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.gz
chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.bz2
This is the O3D source tree's initial commit to the Chromium tree. It
is not built or referenced at all by the chrome build yet, and doesn't yet build in it's new home. We'll change that shortly. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17035 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/samples/o3djs/serialization.js')
-rw-r--r--o3d/samples/o3djs/serialization.js744
1 files changed, 744 insertions, 0 deletions
diff --git a/o3d/samples/o3djs/serialization.js b/o3d/samples/o3djs/serialization.js
new file mode 100644
index 0000000..a8b4ea5
--- /dev/null
+++ b/o3d/samples/o3djs/serialization.js
@@ -0,0 +1,744 @@
+/*
+ * 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 provides support for deserializing (loading)
+ * transform graphs from JSON files.
+ *
+ */
+
+o3djs.provide('o3djs.serialization');
+
+o3djs.require('o3djs.error');
+
+/**
+ * A Module for handling events related to o3d and various browsers.
+ * @namespace
+ */
+o3djs.serialization = o3djs.serialization || {};
+
+/**
+ * The oldest supported version of the serializer. It isn't necessary to
+ * increment this version whenever the format changes. Only change it when the
+ * deserializer becomes incapable of deserializing an older version.
+ * @type {number}
+ */
+o3djs.serialization.supportedVersion = 5;
+
+/**
+ * Options for deserialization.
+ *
+ * opt_animSource is an optional ParamFloat that will be bound as the source
+ * param for all animation time params in the scene. opt_async is a bool that
+ * will make the deserialization process async.
+ *
+ * @type {{opt_animSource: !o3d.ParamFloat, opt_async: boolean}}
+ */
+o3djs.serialization.Options = goog.typedef;
+
+/**
+ * A Deserializer incrementally deserializes a transform graph.
+ * @constructor
+ * @param {!o3d.Pack} pack The pack to deserialize into.
+ * @param {!Object} json An object tree conforming to the JSON rules.
+ */
+o3djs.serialization.Deserializer = function(pack, json) {
+ /**
+ * The pack to deserialize into.
+ * @type {!o3d.Pack}
+ */
+ this.pack = pack;
+
+ /**
+ * An object tree conforming to the JSON rules.
+ * @type {!Object}
+ */
+ this.json = json;
+
+ /**
+ * The archive from which assets referenced from JSON are retreived.
+ * @type {o3djs.io.ArchiveInfo}
+ */
+ this.archiveInfo = null;
+
+ /**
+ * A map from classname to a function that will create
+ * instances of objects. Add entries to support additional classes.
+ * @type {!Object}
+ */
+ this.createCallbacks = {
+ 'o3d.VertexBuffer': function(deserializer, json) {
+ var object = deserializer.pack.createObject('o3d.VertexBuffer');
+ if ('custom' in json) {
+ var rawData = deserializer.archiveInfo.getFileByURI(
+ 'vertex-buffers.bin');
+ object.set(rawData,
+ json.custom.binaryRange[0],
+ json.custom.binaryRange[1] - json.custom.binaryRange[0]);
+ for (var i = 0; i < json.custom.fields.length; ++i) {
+ deserializer.addObject(json.custom.fields[i], object.fields[i]);
+ }
+ }
+ return object;
+ },
+
+ 'o3d.SourceBuffer': function(deserializer, json) {
+ var object = deserializer.pack.createObject('o3d.SourceBuffer');
+ if ('custom' in json) {
+ var rawData = deserializer.archiveInfo.getFileByURI(
+ 'vertex-buffers.bin');
+ object.set(rawData,
+ json.custom.binaryRange[0],
+ json.custom.binaryRange[1] - json.custom.binaryRange[0]);
+ for (var i = 0; i < json.custom.fields.length; ++i) {
+ deserializer.addObject(json.custom.fields[i], object.fields[i]);
+ }
+ }
+ return object;
+ },
+
+ 'o3d.IndexBuffer': function(deserializer, json) {
+ var object = deserializer.pack.createObject('o3d.IndexBuffer');
+ if ('custom' in json) {
+ var rawData = deserializer.archiveInfo.getFileByURI(
+ 'index-buffers.bin');
+ object.set(rawData,
+ json.custom.binaryRange[0],
+ json.custom.binaryRange[1] - json.custom.binaryRange[0]);
+ for (var i = 0; i < json.custom.fields.length; ++i) {
+ deserializer.addObject(json.custom.fields[i], object.fields[i]);
+ }
+ }
+ return object;
+ },
+
+ 'o3d.Texture2D': function(deserializer, json) {
+ if ('o3d.uri' in json.params) {
+ var uri = json.params['o3d.uri'].value;
+ var rawData = deserializer.archiveInfo.getFileByURI(uri);
+ if (!rawData) {
+ throw 'Could not find texture ' + uri + ' in the archive';
+ }
+ return deserializer.pack.createTextureFromRawData(
+ rawData,
+ true);
+ } else {
+ return deserializer.pack.createTexture2D(
+ json.custom.width,
+ json.custom.height,
+ json.custom.format,
+ json.custom.levels,
+ json.custom.renderSurfacesEnabled);
+ }
+ },
+
+ 'o3d.TextureCUBE': function(deserializer, json) {
+ if ('o3d.uri' in json.params) {
+ var uri = json.params['o3d.uri'].value;
+ var rawData = deserializer.archiveInfo.getFileByURI(uri);
+ if (!rawData) {
+ throw 'Could not find texture ' + uri + ' in the archive';
+ }
+ return deserializer.pack.createTextureFromRawData(
+ rawData,
+ true);
+ } else {
+ return deserializer.pack.createTextureCUBE(
+ json.custom.edgeLength,
+ json.custom.format,
+ json.custom.levels,
+ json.custom.renderSurfacesEnabled);
+ }
+ }
+ };
+
+ /**
+ * A map from classname to a function that will initialize
+ * instances of the given class from JSON data. Add entries to support
+ * additional classes.
+ * @type {!Object}
+ */
+ this.initCallbacks = {
+ 'o3d.Curve': function(deserializer, object, json) {
+ if ('custom' in json) {
+ var rawData = deserializer.archiveInfo.getFileByURI('curve-keys.bin');
+ object.set(rawData,
+ json.custom.binaryRange[0],
+ json.custom.binaryRange[1] - json.custom.binaryRange[0]);
+ }
+ },
+
+ 'o3d.Effect': function(deserializer, object, json) {
+ var uriParam = object.getParam('o3d.uri');
+ if (uriParam) {
+ var rawData = deserializer.archiveInfo.getFileByURI(uriParam.value);
+ if (!rawData) {
+ throw 'Cannot find shader ' + uriParam.value + ' in archive.';
+ }
+ if (!object.loadFromFXString(rawData.stringValue)) {
+ throw 'Cannot load shader ' + uriParam.value + ' in archive.';
+ }
+ }
+ },
+
+ 'o3d.Skin': function(deserializer, object, json) {
+ if ('custom' in json) {
+ var rawData = deserializer.archiveInfo.getFileByURI('skins.bin');
+ object.set(rawData,
+ json.custom.binaryRange[0],
+ json.custom.binaryRange[1] - json.custom.binaryRange[0]);
+ }
+ },
+
+ 'o3d.SkinEval': function(deserializer, object, json) {
+ if ('custom' in json) {
+ for (var i = 0; i < json.custom.vertexStreams.length; ++i) {
+ var streamJson = json.custom.vertexStreams[i];
+ var field = deserializer.getObjectById(streamJson.stream.field);
+ object.setVertexStream(streamJson.stream.semantic,
+ streamJson.stream.semanticIndex,
+ field,
+ streamJson.stream.startIndex);
+ if ('bind' in streamJson) {
+ var source = deserializer.getObjectById(streamJson.bind);
+ object.bindStream(source,
+ streamJson.stream.semantic,
+ streamJson.stream.semanticIndex);
+ }
+ }
+ }
+ },
+
+ 'o3d.StreamBank': function(deserializer, object, json) {
+ if ('custom' in json) {
+ for (var i = 0; i < json.custom.vertexStreams.length; ++i) {
+ var streamJson = json.custom.vertexStreams[i];
+ var field = deserializer.getObjectById(streamJson.stream.field);
+ object.setVertexStream(streamJson.stream.semantic,
+ streamJson.stream.semanticIndex,
+ field,
+ streamJson.stream.startIndex);
+ if ('bind' in streamJson) {
+ var source = deserializer.getObjectById(streamJson.bind);
+ object.bindStream(source,
+ streamJson.stream.semantic,
+ streamJson.stream.semanticIndex);
+ }
+ }
+ }
+ }
+ };
+
+ if (!('version' in json)) {
+ throw 'Version in JSON file was missing.';
+ }
+
+ if (json.version < o3djs.serialization.supportedVersion) {
+ throw 'Version in JSON file was ' + json.version +
+ ' but expected at least version ' +
+ o3djs.serialization.supportedVersion + '.';
+ }
+
+ if (!('objects' in json)) {
+ throw 'Objects array in JSON file was missing.';
+ }
+
+ /**
+ * An array of all objects deserialized so far, indexed by object id. Id zero
+ * means null.
+ * @type {!Array.<(Object|undefined)>}
+ * @private
+ */
+ this.objectsById_ = [null];
+
+ /**
+ * An array of objects deserialized so far, indexed by position in the JSON.
+ * @type {!Array.<Object>}
+ * @private
+ */
+ this.objectsByIndex_ = [];
+
+ /**
+ * Array of all classes present in the JSON.
+ * @type {!Array.<string>}
+ * @private
+ */
+ this.classNames_ = [];
+ for (var className in json.objects) {
+ this.classNames_.push(className);
+ }
+
+ /**
+ * The current phase_ of deserialization. In phase_ 0, objects
+ * are created and their ids registered. In phase_ 1, objects are
+ * initialized from JSON data.
+ * @type {number}
+ * @private
+ */
+ this.phase_ = 0;
+
+ /**
+ * Index of the next class to be deserialized in classNames_.
+ * @type {number}
+ * @private
+ */
+ this.nextClassIndex_ = 0;
+
+ /**
+ * Index of the next object of the current class to be deserialized.
+ * @type {number}
+ * @private
+ */
+ this.nextObjectIndex_ = 0;
+
+ /**
+ * Index of the next object to be deserialized in objectsByIndex_.
+ * @type {number}
+ * @private
+ */
+ this.globalObjectIndex_ = 0;
+};
+
+/**
+ * Get the object with the given id.
+ * @param {number} id The id to lookup.
+ * @return {(Object|undefined)} The object with the given id.
+ */
+o3djs.serialization.Deserializer.prototype.getObjectById = function(id) {
+ return this.objectsById_[id];
+};
+
+/**
+ * When a creation or init callback creates an object that the Deserializer
+ * is not aware of, it can associate it with an id using this function, so that
+ * references to the object can be resolved.
+ * @param {number} id The is of the object.
+ * @param {!Object} object The object to register.
+ */
+o3djs.serialization.Deserializer.prototype.addObject = function(
+ id, object) {
+ this.objectsById_[id] = object;
+};
+
+/**
+ * Deserialize a value. Identifies reference values and converts
+ * their object id into an object reference. Otherwise returns the
+ * value unchanged.
+ * @param {*} valueJson The JSON representation of the value.
+ * @return {*} The JavaScript representation of the value.
+ */
+o3djs.serialization.Deserializer.prototype.deserializeValue = function(
+ valueJson) {
+ if (typeof(valueJson) === 'object') {
+ if (valueJson === null) {
+ return null;
+ }
+
+ var valueAsObject = /** @type {!Object} */ (valueJson);
+ if ('length' in valueAsObject) {
+ for (var i = 0; i != valueAsObject.length; ++i) {
+ valueAsObject[i] = this.deserializeValue(valueAsObject[i]);
+ }
+ return valueAsObject;
+ }
+
+ var refId = valueAsObject['ref'];
+ if (refId !== undefined) {
+ var referenced = this.objectsById_[refId];
+ if (referenced === undefined) {
+ throw 'Could not find object with id ' + refId + '.';
+ }
+ return referenced;
+ }
+ }
+
+ return valueJson;
+};
+
+/**
+ * Sets the value of a param on an object or binds a param to another.
+ * @param {!Object} object The object holding the param.
+ * @param {(string|number)} paramName The name of the param.
+ * @param {!Object} propertyJson The JSON representation of the value.
+ * @private
+ */
+o3djs.serialization.Deserializer.prototype.setParamValue_ = function(
+ object, paramName, propertyJson) {
+ var param = object.getParam(paramName);
+ if (param === null)
+ return;
+
+ var valueJson = propertyJson['value'];
+ if (valueJson !== undefined) {
+ param.value = this.deserializeValue(valueJson);
+ }
+
+ var bindId = propertyJson['bind'];
+ if (bindId !== undefined) {
+ var referenced = this.objectsById_[bindId];
+ if (referenced === undefined) {
+ throw 'Could not find output param with id ' + bindId + '.';
+ }
+ param.bind(referenced);
+ }
+};
+
+/**
+ * Creates a param on an object and adds it's id so that other objects can
+ * reference it.
+ * @param {!Object} object The object to hold the param.
+ * @param {(string|number)} paramName The name of the param.
+ * @param {!Object} propertyJson The JSON representation of the value.
+ * @private
+ */
+o3djs.serialization.Deserializer.prototype.createAndIdentifyParam_ =
+ function(object, paramName, propertyJson) {
+ var propertyClass = propertyJson['class'];
+ var param;
+ if (propertyClass !== undefined) {
+ param = object.createParam(paramName, propertyClass);
+ } else {
+ param = object.getParam(paramName);
+ }
+
+ var paramId = propertyJson['id'];
+ if (paramId !== undefined && param !== null) {
+ this.objectsById_[paramId] = param;
+ }
+};
+
+/**
+ * First pass: create all objects and additional params. We need two
+ * passes to support references to objects that appear later in the
+ * JSON.
+ * @param {number} amountOfWork The number of loop iterations to perform of
+ * this phase_.
+ * @private
+ */
+o3djs.serialization.Deserializer.prototype.createObjectsPhase_ =
+ function(amountOfWork) {
+ for (; this.nextClassIndex_ < this.classNames_.length;
+ ++this.nextClassIndex_) {
+ var className = this.classNames_[this.nextClassIndex_];
+ var classJson = this.json.objects[className];
+ var numObjects = classJson.length;
+ for (; this.nextObjectIndex_ < numObjects; ++this.nextObjectIndex_) {
+ if (amountOfWork-- <= 0)
+ return;
+
+ var objectJson = classJson[this.nextObjectIndex_];
+ var object = undefined;
+ if ('id' in objectJson) {
+ object = this.objectsById_[objectJson.id];
+ }
+ if (object === undefined) {
+ if (className in this.createCallbacks) {
+ object = this.createCallbacks[className](this, objectJson);
+ } else {
+ object = this.pack.createObject(className);
+ }
+ }
+ this.objectsByIndex_[this.globalObjectIndex_++] = object;
+ if ('id' in objectJson) {
+ this.objectsById_[objectJson.id] = object;
+ }
+ if ('params' in objectJson) {
+ if ('length' in objectJson.params) {
+ for (var paramIndex = 0; paramIndex != objectJson.params.length;
+ ++paramIndex) {
+ var paramJson = objectJson.params[paramIndex];
+ this.createAndIdentifyParam_(object, paramIndex,
+ paramJson);
+ }
+ } else {
+ for (var paramName in objectJson.params) {
+ var paramJson = objectJson.params[paramName];
+ this.createAndIdentifyParam_(object, paramName, paramJson);
+ }
+ }
+ }
+ }
+ this.nextObjectIndex_ = 0;
+ }
+
+ if (this.nextClassIndex_ === this.classNames_.length) {
+ this.nextClassIndex_ = 0;
+ this.nextObjectIndex_ = 0;
+ this.globalObjectIndex_ = 0;
+ ++this.phase_;
+ }
+};
+
+/**
+ * Second pass: set property and parameter values and bind parameters.
+ * @param {number} amountOfWork The number of loop iterations to perform of
+ * this phase_.
+ * @private
+ */
+o3djs.serialization.Deserializer.prototype.setPropertiesPhase_ = function(
+ amountOfWork) {
+ for (; this.nextClassIndex_ < this.classNames_.length;
+ ++this.nextClassIndex_) {
+ var className = this.classNames_[this.nextClassIndex_];
+ var classJson = this.json.objects[className];
+ var numObjects = classJson.length;
+ for (; this.nextObjectIndex_ < numObjects; ++this.nextObjectIndex_) {
+ if (amountOfWork-- <= 0)
+ return;
+
+ var objectJson = classJson[this.nextObjectIndex_];
+ var object = this.objectsByIndex_[this.globalObjectIndex_++];
+ if ('properties' in objectJson) {
+ for (var propertyName in objectJson.properties) {
+ if (propertyName in object) {
+ var propertyJson = objectJson.properties[propertyName];
+ var propertyValue = this.deserializeValue(propertyJson);
+ object[propertyName] = propertyValue;
+ }
+ };
+ }
+ if ('params' in objectJson) {
+ if ('length' in objectJson.params) {
+ for (var paramIndex = 0; paramIndex != objectJson.params.length;
+ ++paramIndex) {
+ var paramJson = objectJson.params[paramIndex];
+ this.setParamValue_(/** @type {!Object} */ (object),
+ paramIndex,
+ paramJson);
+ }
+ } else {
+ for (var paramName in objectJson.params) {
+ var paramJson = objectJson.params[paramName];
+ this.setParamValue_(/** @type {!Object} */ (object),
+ paramName,
+ paramJson);
+ }
+ }
+ }
+ if (className in this.initCallbacks) {
+ this.initCallbacks[className](this, object, objectJson);
+ }
+ }
+ this.nextObjectIndex_ = 0;
+ }
+
+ if (this.nextClassIndex_ === this.classNames_.length) {
+ this.nextClassIndex_ = 0;
+ this.nextObjectIndex_ = 0;
+ this.globalObjectIndex_ = 0;
+ ++this.phase_;
+ }
+};
+
+/**
+ * Perform a certain number of iterations of the deserializer. Keep calling this
+ * function until it returns false.
+ * @param {number} opt_amountOfWork The number of loop iterations to run. If
+ * not specified, runs the deserialization to completion.
+ * @return {boolean} Whether work remains to be done.
+ */
+o3djs.serialization.Deserializer.prototype.run = function(
+ opt_amountOfWork) {
+ if (!opt_amountOfWork) {
+ while (this.run(10000)) {
+ }
+ return false;
+ } else {
+ switch (this.phase_) {
+ case 0:
+ this.createObjectsPhase_(opt_amountOfWork);
+ break;
+ case 1:
+ this.setPropertiesPhase_(opt_amountOfWork);
+ break;
+ }
+ return this.phase_ < 2;
+ }
+};
+
+/**
+ * Deserializes (loads) a transform graph in the background. Invokes
+ * a callback function on completion passing the pack and the thrown
+ * exception on failure or the pack and a null exception on success.
+ * @param {!o3d.Client} client An O3D client object.
+ * @param {!o3d.Pack} pack The pack to create the deserialized objects
+ * in.
+ * @param {number} time The amount of the time (in seconds) the deserializer
+ * should aim to complete in.
+ * @param {!function(o3d.Pack, *): void} callback The function that
+ * is called on completion. The second parameter is null on success or
+ * the thrown exception on failure.
+ */
+o3djs.serialization.Deserializer.prototype.runBackground = function(
+ client, pack, time, callback) {
+ // TODO: This seems like it needs to be more granular than the
+ // top level.
+ // TODO: Passing in the time you want it to take seems counter
+ // intuitive. I want pass in a % of CPU so I can effectively say
+ // "deserialize this in such a way so as not to affect my app's
+ // performance". callbacksRequired = numObjects / amountPerCallback where
+ // amountPerCallback = number I can do per frame and not affect performance
+ // too much.
+ var workToDo = this.json.objects.length * 2;
+ var timerCallbacks = time * 60;
+ var amountPerCallback = workToDo / timerCallbacks;
+ var intervalId;
+ var that = this;
+ function deserializeMore() {
+ var exception = null;
+ var finished = false;
+ var failed = false;
+ var errorCollector = o3djs.error.createErrorCollector(client);
+ try {
+ finished = !that.run(amountPerCallback);
+ } catch(e) {
+ failed = true;
+ finished = true;
+ exception = e;
+ }
+ if (errorCollector.errors.length > 0) {
+ finished = true;
+ exception = errorCollector.errors.join('\n') +
+ (exception ? ('\n' + exception.toString()) : '');
+ }
+ errorCollector.finish();
+ if (finished) {
+ window.clearInterval(intervalId);
+ callback(pack, exception);
+ }
+ }
+
+ intervalId = window.setInterval(deserializeMore, 1000 / 60);
+};
+
+/**
+ * Creates a deserializer that will incrementally deserialize a
+ * transform graph. The deserializer object has a method
+ * called run that does a fixed amount of work and returns.
+ * It returns true until the transform graph is fully deserialized.
+ * It returns false from then on.
+ * @param {!o3d.Pack} pack The pack to create the deserialized
+ * objects in.
+ * @param {!Object} json An object tree conforming to the JSON rules.
+ * @return {!o3djs.serialization.Deserializer} A deserializer object.
+ */
+o3djs.serialization.createDeserializer = function(pack, json) {
+ return new o3djs.serialization.Deserializer(pack, json);
+};
+
+/**
+ * Deserializes a transform graph.
+ * @param {!o3d.Pack} pack The pack to create the deserialized
+ * objects in.
+ * @param {!Object} json An object tree conforming to the JSON rules.
+ */
+o3djs.serialization.deserialize = function(pack, json) {
+ var deserializer = o3djs.serialization.createDeserializer(pack, json);
+ deserializer.run();
+};
+
+/**
+ * Deserializes a single json object named 'scene.json' from a loaded
+ * o3djs.io.ArchiveInfo.
+ * @param {!o3djs.io.archiveInfo} archiveInfo Archive to load from.
+ * @param {string} sceneJsonUri The relative URI of the scene JSON file within
+ * the archive.
+ * @param {!o3d.Client} client An O3D client object.
+ * @param {!o3d.Pack} pack The pack to create the deserialized objects
+ * in.
+ * @param {!o3d.Transform} parent Transform to parent loaded stuff from.
+ * @param {!function(!o3d.Pack, !o3d.Transform, *): void} callback A function
+ * that will be called when deserialization is finished. It will be passed
+ * the pack, the parent transform, and an exception which will be null on
+ * success.
+ * @param {!o3djs.serialization.Options} opt_options Options.
+ */
+o3djs.serialization.deserializeArchive = function(archiveInfo,
+ sceneJsonUri,
+ client,
+ pack,
+ parent,
+ callback,
+ opt_options) {
+ opt_options = opt_options || { };
+ var jsonFile = archiveInfo.getFileByURI(sceneJsonUri);
+ if (!jsonFile) {
+ throw 'Could not find ' + sceneJsonUri + ' in archive';
+ }
+ var parsed = eval('(' + jsonFile.stringValue + ')');
+ var deserializer = o3djs.serialization.createDeserializer(pack, parsed);
+
+ deserializer.addObject(parsed.o3d_rootObject_root, parent);
+ deserializer.archiveInfo = archiveInfo;
+
+ var finishCallback = function(pack, exception) {
+ if (!exception) {
+ var objects = pack.getObjects('o3d.animSourceOwner', 'o3d.ParamObject');
+ if (objects.length > 0) {
+ // Rebind the output connections of the animSource to the user's param.
+ if (opt_options.opt_animSource) {
+ var animSource = objects[0].getParam('animSource');
+ var outputConnections = animSource.outputConnections;
+ for (var ii = 0; ii < outputConnections.length; ++ii) {
+ outputConnections[ii].bind(opt_options.opt_animSource);
+ }
+ }
+ // Remove special object from pack.
+ for (var ii = 0; ii < objects.length; ++ii) {
+ pack.removeObject(objects[ii]);
+ }
+ }
+ }
+ callback(pack, parent, exception);
+ };
+
+ if (opt_options.opt_async) {
+ // TODO: Remove the 5. See deserializer.runBackground comments.
+ deserializer.runBackground(client, pack, 5, finishCallback);
+ } else {
+ var exception = null;
+ var errorCollector = o3djs.error.createErrorCollector(client);
+ try {
+ deserializer.run();
+ } catch (e) {
+ exception = e;
+ }
+ if (errorCollector.errors.length > 0) {
+ exception = errorCollector.errors.join('\n') +
+ (exception ? ('\n' + exception.toString()) : '');
+ }
+ errorCollector.finish();
+ finishCallback(pack, exception);
+ }
+};
+
+