Index: samples/o3d-webgl/archive_request.js |
=================================================================== |
--- samples/o3d-webgl/archive_request.js (revision 0) |
+++ samples/o3d-webgl/archive_request.js (revision 0) |
@@ -0,0 +1,268 @@ |
+/* |
+ * Copyright 2010, 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. |
+ */ |
+ |
+// TODO(kbr): figure out how we can reuse the o3djs.io package from |
+// within here. |
+// o3djs.require('o3djs.io'); |
+ |
+// TODO(kbr): factor this out into e.g. o3djs.json and require |
+// o3djs.json here. |
+if(!this.JSON){this.JSON={};} |
+(function(){function f(n){return n<10?'0'+n:n;} |
+if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+ |
+f(this.getUTCMonth()+1)+'-'+ |
+f(this.getUTCDate())+'T'+ |
+f(this.getUTCHours())+':'+ |
+f(this.getUTCMinutes())+':'+ |
+f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};} |
+var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';} |
+function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);} |
+if(typeof rep==='function'){value=rep.call(holder,key,value);} |
+switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';} |
+gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';} |
+v=partial.length===0?'[]':gap?'[\n'+gap+ |
+partial.join(',\n'+gap)+'\n'+ |
+mind+']':'['+partial.join(',')+']';gap=mind;return v;} |
+if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}} |
+v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+ |
+mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}} |
+if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;} |
+rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');} |
+return str('',{'':value});};} |
+if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}} |
+return reviver.call(holder,key,value);} |
+text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+ |
+('0000'+a.charCodeAt(0).toString(16)).slice(-4);});} |
+if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;} |
+throw new SyntaxError('JSON.parse');};}}()); |
+ |
+ |
+/** |
+ An ArchiveRequest object is used to carry out an asynchronous request for a |
+ compressed archive (containing multiple files). |
+ |
+ Note: The archive must have as its first file a file named 'aaaaaaaa.o3d' |
+ who's contents is 'o3d'. This is to prevent O3D being used to open |
+ archive files that were not meant for it. |
+ |
+ \code |
+ var request = pack.createArchiveRequest(); |
+ request.open("GET", url); |
+ |
+ request.onfileavailable = myFileAvailableCallback; |
+ request.onreadystatechange = myReadyStateChangeCallback; |
+ request.send(); |
+ |
+ function myFileAvailableCallback(rawData) { |
+ dump("uri: " + rawData.uri + "\n"); |
+ dump("content: " + rawData.stringValue + "\n"); |
+ |
+ // You can pass a RawData to various creation functions. Note: rawData |
+ // is only valid until you remove the request. |
+ // Examples: |
+ if (rawData.uri == 'mytexture.jpg') |
+ pack.createTexture2d(rawData, makeMips); |
+ if (rawData.uri == 'myvertices.bin') |
+ vertexBuffer.set(rawData); |
+ if (rawData.uri == 'myAudio.mp3') |
+ audioSystem.createSound(rawData); |
+ } |
+ |
+ function myReadyStateChangeCallback() { |
+ if (request.done) { |
+ if (request.success) { |
+ // there were no errors trying to read the archive |
+ } else { |
+ dump(request.error); |
+ } |
+ } |
+ } |
+ |
+ // When you are done with the RawDatas loaded by the request, remove |
+ // the request from the pack to free them. |
+ pack.removeObject(request); |
+*/ |
+ |
+o3d.ArchiveRequest = function() { |
+ o3d.ObjectBase.call(this); |
+ this.method_ = null; |
+}; |
+o3d.inherit('ArchiveRequest', 'ObjectBase'); |
+ |
+/** |
+ * The URI this request is for. |
+ * @type {string} |
+ */ |
+o3d.ArchiveRequest.prototype.uri = ''; |
+ |
+/** |
+ * Set up several of the request fields. |
+ * @param {string} method "GET" is the only supported method at this time |
+ * @param {string} uri the location of the file to fetch |
+ * @param {boolean} async true is the only legal value at this time. |
+ */ |
+o3d.ArchiveRequest.prototype.open = |
+ function(method, uri) { |
+ this.uri = uri; |
+ |
+ // Compute the parent directory of this URI. |
+ var parentURI = uri; |
+ var lastSlash = uri.lastIndexOf('/'); |
+ if (lastSlash != -1) { |
+ parentURI = parentURI.substring(0, lastSlash + 1); |
+ } |
+ |
+ this.parentURI_ = parentURI; |
+}; |
+ |
+/** |
+ * Send the request. |
+ * Unlike XMLHttpRequest the onreadystatechange callback will be called no |
+ * matter what, with success or failure. |
+ */ |
+o3d.ArchiveRequest.prototype.send = function() { |
+ var that = this; |
+ this.done = false; |
+ this.success = true; |
+ this.error = null; |
+ var callback = function(sourceJSON, exc) { |
+ // Don't send down the original scene.json because 'eval' is used |
+ // elsewhere to reconstitute it, which is risky. |
+ var filteredJSON = JSON.stringify(JSON.parse(sourceJSON)); |
+ |
+ if (that.onfileavailable) { |
+ var rawData = new o3d.RawData(); |
+ rawData.uri = 'scene.json'; |
+ rawData.stringValue = filteredJSON; |
+ that.onfileavailable(rawData); |
+ } |
+ |
+ // In o3d-webgl, the "archive" is really just the top-level |
+ // scene.json. We run a regexp on it to find URIs for certain |
+ // well-known file types (.fx, .png, .jpg) and issue file requests |
+ // for them. |
+ var uriRegex = /\"([^\"]*\.(fx|png|jpg))\"/g; |
+ var matchArray; |
+ var uris = []; |
+ while ((matchArray = uriRegex.exec(sourceJSON)) != null) { |
+ uris.push(matchArray[1]); |
+ } |
+ |
+ that.pendingRequests_ = uris.length; |
+ |
+ // Issue requests for each of these URIs. |
+ for (var ii = 0; ii < uris.length; ++ii) { |
+ if (that.stringEndsWith_(uris[ii], ".fx")) { |
+ var func = function(uri) { |
+ var completion = function(value, exc) { |
+ var rawData = null; |
+ if (exc == null) { |
+ rawData = new o3d.RawData(); |
+ rawData.uri = uri; |
+ rawData.stringValue = value; |
+ } |
+ that.decrementPendingRequests_(rawData, exc); |
+ }; |
+ o3djs.io.loadTextFile(that.relativeToAbsoluteURI_(uri), |
+ completion); |
+ }; |
+ func(uris[ii]); |
+ } else if (that.stringEndsWith_(uris[ii], ".png") || |
+ that.stringEndsWith_(uris[ii], ".jpg")) { |
+ var func = function(uri) { |
+ var image = new Image(); |
+ image.onload = function() { |
+ var rawData = new o3d.RawData(); |
+ rawData.uri = uri; |
+ rawData.image_ = image; |
+ that.decrementPendingRequests_(rawData, exc); |
+ }; |
+ image.onerror = function() { |
+ that.decrementPendingRequests_(null, exc); |
+ } |
+ image.src = that.relativeToAbsoluteURI_(uri); |
+ }; |
+ func(uris[ii]); |
+ } |
+ } |
+ }; |
+ |
+ o3djs.io.loadTextFile(this.uri, callback); |
+}; |
+ |
+/** |
+ * A callback to call whenever the ready state of the request changes. |
+ * @type {function(): void} |
+ */ |
+o3d.ArchiveRequest.prototype.onreadystatechange = null; |
+ |
+/** |
+ * A callback to call when each file comes in. |
+ * @type {function(!o3d.RawData): void} |
+ */ |
+o3d.ArchiveRequest.prototype.onfileavailable = null; |
+ |
+/** |
+ * Converts a local URI to an absolute URI. |
+ * @private |
+ */ |
+o3d.ArchiveRequest.prototype.relativeToAbsoluteURI_ = function(relativeURI) { |
+ return this.parentURI_ + relativeURI; |
+}; |
+ |
+/** |
+ * Indicates whether one string ends with another. |
+ * @private |
+ */ |
+o3d.ArchiveRequest.prototype.stringEndsWith_ = function(string, suffix) { |
+ return string.substring(string.length - suffix.length) == suffix; |
+}; |
+ |
+/** |
+ * Decrements the number of pending requests. |
+ * @private |
+ */ |
+o3d.ArchiveRequest.prototype.decrementPendingRequests_ = |
+ function(rawData, opt_exc) { |
+ this.success = this.success && rawData && (!opt_exc); |
+ if (opt_exc != null) { |
+ this.error = "" + opt_exc; |
+ } |
+ if (rawData && this.onfileavailable) { |
+ this.onfileavailable(rawData); |
+ } |
+ if (--this.pendingRequests_ == 0) { |
+ this.done = true; |
+ if (this.onreadystatechange) { |
+ this.onreadystatechange(); |
+ } |
+ } |
+}; |
Property changes on: samples/o3d-webgl/archive_request.js |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |