this.data.length;)this.currentTime-=this.data.length;k=this.currentTime%=this.data.length;parseInt(Math.min(k*this.data.fps,this.data.length*this.data.fps),10);for(var n=0,p=this.hierarchy.length;nt;t++){c=b[t];g=i.prevKey[c];h=i.nextKey[c];if(h.time<=l){if(k<=l)if(this.loop){g=
+this.data.hierarchy[n].keys[0];for(h=this.getNextKeyWith(c,n,1);null!==h&&h.timeg.index;)g=h,h=this.getNextKeyWith(c,n,h.index+1)}else{this.stop();return}else{do g=h,h=this.getNextKeyWith(c,n,h.index+1);while(null!==h&&h.timeg.index)}i.prevKey[c]=g;i.nextKey[c]=h}a.matrixAutoUpdate=!0;a.matrixWorldNeedsUpdate=!0;d=(k-g.time)/(h.time-g.time);e=g[c];f=h[c];if(0>d||1d?0:1;if("pos"===c)if(c=
+a.position,this.interpolationType===THREE.AnimationHandler.LINEAR)c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+(f[2]-e[2])*d;else{if(this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD)this.points[0]=this.getPrevKeyWith("pos",n,g.index-1).pos,this.points[1]=e,this.points[2]=f,this.points[3]=this.getNextKeyWith("pos",n,h.index+1).pos,d=0.33*d+0.33,e=this.interpolateCatmullRom(this.points,d),c.x=e[0],c.y=e[1],c.z=e[2],
+this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD&&(d=this.interpolateCatmullRom(this.points,1.01*d),this.target.set(d[0],d[1],d[2]),this.target.sub(c),this.target.y=0,this.target.normalize(),d=Math.atan2(this.target.x,this.target.z),a.rotation.set(0,d,0))}else"rot"===c?THREE.Quaternion.slerp(e,f,a.quaternion,d):"scl"===c&&(c=a.scale,c.x=e[0]+(f[0]-e[0])*d,c.y=e[1]+(f[1]-e[1])*d,c.z=e[2]+(f[2]-e[2])*d)}}}};
+THREE.Animation.prototype.interpolateCatmullRom=function(a,b){var c=[],d=[],e,f,g,h,i,k;e=(a.length-1)*b;f=Math.floor(e);e-=f;c[0]=0===f?f:f-1;c[1]=f;c[2]=f>a.length-2?f:f+1;c[3]=f>a.length-3?f:f+2;f=a[c[0]];h=a[c[1]];i=a[c[2]];k=a[c[3]];c=e*e;g=e*c;d[0]=this.interpolate(f[0],h[0],i[0],k[0],e,c,g);d[1]=this.interpolate(f[1],h[1],i[1],k[1],e,c,g);d[2]=this.interpolate(f[2],h[2],i[2],k[2],e,c,g);return d};
+THREE.Animation.prototype.interpolate=function(a,b,c,d,e,f,g){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*g+(-3*(b-c)-2*a-d)*f+a*e+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c=g?b.interpolate(c,g):b.interpolate(c,c.time)}this.data.hierarchy[a].node.updateMatrix();d.matrixWorldNeedsUpdate=!0}}if(this.JITCompile&&void 0===f[0][e]){this.hierarchy[0].updateMatrixWorld(!0);for(a=0;ag?(b=Math.atan2(b.y-a.y,b.x-a.x),a=Math.atan2(c.y-a.y,c.x-a.x),b>a&&(a+=2*Math.PI),c=(b+a)/2,a=-Math.cos(c),c=-Math.sin(c),new THREE.Vector2(a,c)):d.multiplyScalar(g).add(h).sub(a).clone()}function e(c,d){var e,f;for(O=c.length;0<=--O;){e=O;f=O-1;0>f&&(f=c.length-1);for(var g=0,h=t+2*l,
+g=0;gMath.abs(c-i)?[new THREE.Vector2(b,1-e),new THREE.Vector2(d,1-f),new THREE.Vector2(k,1-g),new THREE.Vector2(n,1-a)]:[new THREE.Vector2(c,1-e),new THREE.Vector2(i,1-f),new THREE.Vector2(l,1-g),new THREE.Vector2(p,1-a)]}};THREE.ExtrudeGeometry.__v1=new THREE.Vector2;THREE.ExtrudeGeometry.__v2=new THREE.Vector2;THREE.ExtrudeGeometry.__v3=new THREE.Vector2;THREE.ExtrudeGeometry.__v4=new THREE.Vector2;
+THREE.ExtrudeGeometry.__v5=new THREE.Vector2;THREE.ExtrudeGeometry.__v6=new THREE.Vector2;THREE.ShapeGeometry=function(a,b){THREE.Geometry.call(this);!1===a instanceof Array&&(a=[a]);this.shapebb=a[a.length-1].getBoundingBox();this.addShapeList(a,b);this.computeCentroids();this.computeFaceNormals()};THREE.ShapeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ShapeGeometry.prototype.addShapeList=function(a,b){for(var c=0,d=a.length;cc&&1===a.x&&(a=new THREE.Vector2(a.x-1,a.y));0===b.x&&0===b.z&&(a=new THREE.Vector2(c/2/Math.PI+0.5,a.y));return a.clone()}THREE.Geometry.call(this);for(var c=c||1,d=d||0,h=this,i=0,k=a.length;ip&&(0.2>a&&(d[0].x+=1),0.2>b&&(d[1].x+=1),0.2>l&&(d[2].x+=1));i=0;for(k=this.vertices.length;ic.y?this.quaternion.set(1,0,0,0):(a.set(c.z,0,-c.x).normalize(),b=Math.acos(c.y),this.quaternion.setFromAxisAngle(a,b))}}();
+THREE.ArrowHelper.prototype.setLength=function(a,b,c){void 0===b&&(b=0.2*a);void 0===c&&(c=0.2*b);this.line.scale.set(1,a,1);this.line.updateMatrix();this.cone.scale.set(c,b,c);this.cone.position.y=a;this.cone.updateMatrix()};THREE.ArrowHelper.prototype.setColor=function(a){this.line.material.color.setHex(a);this.cone.material.color.setHex(a)};THREE.BoxHelper=function(a){var b=[new THREE.Vector3(1,1,1),new THREE.Vector3(-1,1,1),new THREE.Vector3(-1,-1,1),new THREE.Vector3(1,-1,1),new THREE.Vector3(1,1,-1),new THREE.Vector3(-1,1,-1),new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,-1,-1)];this.vertices=b;var c=new THREE.Geometry;c.vertices.push(b[0],b[1],b[1],b[2],b[2],b[3],b[3],b[0],b[4],b[5],b[5],b[6],b[6],b[7],b[7],b[4],b[0],b[4],b[1],b[5],b[2],b[6],b[3],b[7]);THREE.Line.call(this,c,new THREE.LineBasicMaterial({color:16776960}),THREE.LinePieces);
+void 0!==a&&this.update(a)};THREE.BoxHelper.prototype=Object.create(THREE.Line.prototype);
+THREE.BoxHelper.prototype.update=function(a){var b=a.geometry;null===b.boundingBox&&b.computeBoundingBox();var c=b.boundingBox.min,b=b.boundingBox.max,d=this.vertices;d[0].set(b.x,b.y,b.z);d[1].set(c.x,b.y,b.z);d[2].set(c.x,c.y,b.z);d[3].set(b.x,c.y,b.z);d[4].set(b.x,b.y,c.z);d[5].set(c.x,b.y,c.z);d[6].set(c.x,c.y,c.z);d[7].set(b.x,c.y,c.z);this.geometry.computeBoundingSphere();this.geometry.verticesNeedUpdate=!0;this.matrixAutoUpdate=!1;this.matrixWorld=a.matrixWorld};THREE.BoundingBoxHelper=function(a,b){var c=void 0!==b?b:8947848;this.object=a;this.box=new THREE.Box3;THREE.Mesh.call(this,new THREE.CubeGeometry(1,1,1),new THREE.MeshBasicMaterial({color:c,wireframe:!0}))};THREE.BoundingBoxHelper.prototype=Object.create(THREE.Mesh.prototype);THREE.BoundingBoxHelper.prototype.update=function(){this.box.setFromObject(this.object);this.box.size(this.scale);this.box.center(this.position)};THREE.CameraHelper=function(a){function b(a,b,d){c(a,d);c(b,d)}function c(a,b){d.vertices.push(new THREE.Vector3);d.colors.push(new THREE.Color(b));void 0===f[a]&&(f[a]=[]);f[a].push(d.vertices.length-1)}var d=new THREE.Geometry,e=new THREE.LineBasicMaterial({color:16777215,vertexColors:THREE.FaceColors}),f={};b("n1","n2",16755200);b("n2","n4",16755200);b("n4","n3",16755200);b("n3","n1",16755200);b("f1","f2",16755200);b("f2","f4",16755200);b("f4","f3",16755200);b("f3","f1",16755200);b("n1","f1",16755200);
+b("n2","f2",16755200);b("n3","f3",16755200);b("n4","f4",16755200);b("p","n1",16711680);b("p","n2",16711680);b("p","n3",16711680);b("p","n4",16711680);b("u1","u2",43775);b("u2","u3",43775);b("u3","u1",43775);b("c","t",16777215);b("p","c",3355443);b("cn1","cn2",3355443);b("cn3","cn4",3355443);b("cf1","cf2",3355443);b("cf3","cf4",3355443);THREE.Line.call(this,d,e,THREE.LinePieces);this.camera=a;this.matrixWorld=a.matrixWorld;this.matrixAutoUpdate=!1;this.pointMap=f;this.update()};
+THREE.CameraHelper.prototype=Object.create(THREE.Line.prototype);
+THREE.CameraHelper.prototype.update=function(){var a=new THREE.Vector3,b=new THREE.Camera,c=new THREE.Projector;return function(){function d(d,g,h,i){a.set(g,h,i);c.unprojectVector(a,b);d=e.pointMap[d];if(void 0!==d){g=0;for(h=d.length;gr;r++){d[0]=t[g[r]];d[1]=t[g[(r+1)%3]];d.sort(f);var m=d.toString();void 0===e[m]?(e[m]={vert1:d[0],vert2:d[1],face1:n,face2:void 0},l++):e[m].face2=n}h.addAttribute("position",Float32Array,2*l,3);d=h.attributes.position.array;
+f=0;for(m in e)if(g=e[m],void 0===g.face2||0.9999>i[g.face1].normal.dot(i[g.face2].normal))l=k[g.vert1],d[f++]=l.x,d[f++]=l.y,d[f++]=l.z,l=k[g.vert2],d[f++]=l.x,d[f++]=l.y,d[f++]=l.z;THREE.Line.call(this,h,new THREE.LineBasicMaterial({color:c}),THREE.LinePieces);this.matrixAutoUpdate=!1;this.matrixWorld=a.matrixWorld};THREE.EdgesHelper.prototype=Object.create(THREE.Line.prototype);THREE.FaceNormalsHelper=function(a,b,c,d){this.object=a;this.size=void 0!==b?b:1;for(var a=void 0!==c?c:16776960,d=void 0!==d?d:1,b=new THREE.Geometry,c=0,e=this.object.geometry.faces.length;cd;d++)c.faces[d].color=this.colors[4>d?0:1];d=new THREE.MeshBasicMaterial({vertexColors:THREE.FaceColors,wireframe:!0});this.lightSphere=new THREE.Mesh(c,d);this.add(this.lightSphere);
+this.update()};THREE.HemisphereLightHelper.prototype=Object.create(THREE.Object3D.prototype);THREE.HemisphereLightHelper.prototype.dispose=function(){this.lightSphere.geometry.dispose();this.lightSphere.material.dispose()};
+THREE.HemisphereLightHelper.prototype.update=function(){var a=new THREE.Vector3;return function(){this.colors[0].copy(this.light.color).multiplyScalar(this.light.intensity);this.colors[1].copy(this.light.groundColor).multiplyScalar(this.light.intensity);this.lightSphere.lookAt(a.setFromMatrixPosition(this.light.matrixWorld).negate());this.lightSphere.geometry.colorsNeedUpdate=!0}}();THREE.PointLightHelper=function(a,b){this.light=a;this.light.updateMatrixWorld();var c=new THREE.SphereGeometry(b,4,2),d=new THREE.MeshBasicMaterial({wireframe:!0,fog:!1});d.color.copy(this.light.color).multiplyScalar(this.light.intensity);THREE.Mesh.call(this,c,d);this.matrixWorld=this.light.matrixWorld;this.matrixAutoUpdate=!1};THREE.PointLightHelper.prototype=Object.create(THREE.Mesh.prototype);THREE.PointLightHelper.prototype.dispose=function(){this.geometry.dispose();this.material.dispose()};
+THREE.PointLightHelper.prototype.update=function(){this.material.color.copy(this.light.color).multiplyScalar(this.light.intensity)};THREE.SpotLightHelper=function(a){THREE.Object3D.call(this);this.light=a;this.light.updateMatrixWorld();this.matrixWorld=a.matrixWorld;this.matrixAutoUpdate=!1;a=new THREE.CylinderGeometry(0,1,1,8,1,!0);a.applyMatrix((new THREE.Matrix4).makeTranslation(0,-0.5,0));a.applyMatrix((new THREE.Matrix4).makeRotationX(-Math.PI/2));var b=new THREE.MeshBasicMaterial({wireframe:!0,fog:!1});this.cone=new THREE.Mesh(a,b);this.add(this.cone);this.update()};THREE.SpotLightHelper.prototype=Object.create(THREE.Object3D.prototype);
+THREE.SpotLightHelper.prototype.dispose=function(){this.cone.geometry.dispose();this.cone.material.dispose()};THREE.SpotLightHelper.prototype.update=function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(){var c=this.light.distance?this.light.distance:1E4,d=c*Math.tan(this.light.angle);this.cone.scale.set(d,d,c);a.setFromMatrixPosition(this.light.matrixWorld);b.setFromMatrixPosition(this.light.target.matrixWorld);this.cone.lookAt(b.sub(a));this.cone.material.color.copy(this.light.color).multiplyScalar(this.light.intensity)}}();THREE.VertexNormalsHelper=function(a,b,c,d){this.object=a;this.size=void 0!==b?b:1;for(var b=void 0!==c?c:16711680,d=void 0!==d?d:1,c=new THREE.Geometry,a=a.geometry.faces,e=0,f=a.length;em;m++){d[0]=r[g[m]];d[1]=r[g[(m+1)%3]];d.sort(f);var q=d.toString();void 0===e[q]&&(n[2*l]=d[0],n[2*l+1]=d[1],e[q]=!0,l++)}h.addAttribute("position",Float32Array,2*l,3);d=h.attributes.position.array;
+p=0;for(t=l;pm;m++)l=i[n[2*p+m]],g=6*p+3*m,d[g+0]=l.x,d[g+1]=l.y,d[g+2]=l.z}else if(a.geometry instanceof THREE.BufferGeometry&&void 0!==a.geometry.attributes.index){for(var i=a.geometry.attributes.position.array,t=a.geometry.attributes.index.array,k=a.geometry.offsets,l=0,n=new Uint32Array(2*t.length),r=0,u=k.length;rm;m++)d[0]=g+t[p+m],d[1]=g+t[p+(m+1)%3],d.sort(f),q=d.toString(),void 0===e[q]&&(n[2*
+l]=d[0],n[2*l+1]=d[1],e[q]=!0,l++);h.addAttribute("position",Float32Array,2*l,3);d=h.attributes.position.array;p=0;for(t=l;pm;m++)g=6*p+3*m,l=3*n[2*p+m],d[g+0]=i[l],d[g+1]=i[l+1],d[g+2]=i[l+2]}else if(a.geometry instanceof THREE.BufferGeometry){i=a.geometry.attributes.position.array;l=i.length/3;n=l/3;h.addAttribute("position",Float32Array,2*l,3);d=h.attributes.position.array;p=0;for(t=n;pm;m++)g=18*p+6*m,n=9*p+3*m,d[g+0]=i[n],d[g+1]=i[n+1],d[g+2]=i[n+2],l=9*p+3*
+((m+1)%3),d[g+3]=i[l],d[g+4]=i[l+1],d[g+5]=i[l+2]}THREE.Line.call(this,h,new THREE.LineBasicMaterial({color:c}),THREE.LinePieces);this.matrixAutoUpdate=!1;this.matrixWorld=a.matrixWorld};THREE.WireframeHelper.prototype=Object.create(THREE.Line.prototype);THREE.ImmediateRenderObject=function(){THREE.Object3D.call(this);this.render=function(){}};THREE.ImmediateRenderObject.prototype=Object.create(THREE.Object3D.prototype);THREE.LensFlare=function(a,b,c,d,e){THREE.Object3D.call(this);this.lensFlares=[];this.positionScreen=new THREE.Vector3;this.customUpdateCallback=void 0;void 0!==a&&this.add(a,b,c,d,e)};THREE.LensFlare.prototype=Object.create(THREE.Object3D.prototype);
+THREE.LensFlare.prototype.add=function(a,b,c,d,e,f){void 0===b&&(b=-1);void 0===c&&(c=0);void 0===f&&(f=1);void 0===e&&(e=new THREE.Color(16777215));void 0===d&&(d=THREE.NormalBlending);c=Math.min(c,Math.max(0,c));this.lensFlares.push({texture:a,size:b,distance:c,x:0,y:0,z:0,scale:1,rotation:1,opacity:f,color:e,blending:d})};
+THREE.LensFlare.prototype.updateLensFlares=function(){var a,b=this.lensFlares.length,c,d=2*-this.positionScreen.x,e=2*-this.positionScreen.y;for(a=0;ah.end&&(h.end=f);c||(c=i)}}for(i in d)h=d[i],this.createAnimation(i,h.start,h.end,a);this.firstAnimation=c};
+THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a])a.direction=1,a.directionBackwards=!1};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a])a.direction=-1,a.directionBackwards=!0};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];c&&(c.fps=b,c.duration=(c.end-c.start)/c.fps)};
+THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];c&&(c.duration=b,c.fps=(c.end-c.start)/c.duration)};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];c&&(c.weight=b)};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];c&&(c.time=b)};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b};
+THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];b?(b.time=0,b.active=!0):console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=!1};
+THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;bd.duration||0>d.time)d.direction*=-1,d.time>d.duration&&(d.time=d.duration,d.directionBackwards=!0),0>d.time&&(d.time=0,d.directionBackwards=!1)}else d.time%=d.duration,0>d.time&&(d.time+=d.duration);var f=d.startFrame+THREE.Math.clamp(Math.floor(d.time/e),0,d.length-1),g=d.weight;
+f!==d.currentFrame&&(this.morphTargetInfluences[d.lastFrame]=0,this.morphTargetInfluences[d.currentFrame]=1*g,this.morphTargetInfluences[f]=0,d.lastFrame=d.currentFrame,d.currentFrame=f);e=d.time%e/e;d.directionBackwards&&(e=1-e);this.morphTargetInfluences[d.currentFrame]=e*g;this.morphTargetInfluences[d.lastFrame]=(1-e)*g}}};THREE.LensFlarePlugin=function(){function a(a,c){var d=b.createProgram(),e=b.createShader(b.FRAGMENT_SHADER),f=b.createShader(b.VERTEX_SHADER),g="precision "+c+" float;\n";b.shaderSource(e,g+a.fragmentShader);b.shaderSource(f,g+a.vertexShader);b.compileShader(e);b.compileShader(f);b.attachShader(d,e);b.attachShader(d,f);b.linkProgram(d);return d}var b,c,d,e,f,g,h,i,k,l,n,p,t;this.init=function(r){b=r.context;c=r;d=r.getPrecision();e=new Float32Array(16);f=new Uint16Array(6);r=0;e[r++]=-1;e[r++]=-1;
+e[r++]=0;e[r++]=0;e[r++]=1;e[r++]=-1;e[r++]=1;e[r++]=0;e[r++]=1;e[r++]=1;e[r++]=1;e[r++]=1;e[r++]=-1;e[r++]=1;e[r++]=0;e[r++]=1;r=0;f[r++]=0;f[r++]=1;f[r++]=2;f[r++]=0;f[r++]=2;f[r++]=3;g=b.createBuffer();h=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,g);b.bufferData(b.ARRAY_BUFFER,e,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.bufferData(b.ELEMENT_ARRAY_BUFFER,f,b.STATIC_DRAW);i=b.createTexture();k=b.createTexture();b.bindTexture(b.TEXTURE_2D,i);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,
+0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,k);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);
+b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);0>=b.getParameter(b.MAX_VERTEX_TEXTURE_IMAGE_UNITS)?(l=!1,n=a(THREE.ShaderFlares.lensFlare,d)):(l=!0,n=a(THREE.ShaderFlares.lensFlareVertexTexture,d));p={};t={};p.vertex=b.getAttribLocation(n,"position");p.uv=b.getAttribLocation(n,"uv");t.renderType=b.getUniformLocation(n,"renderType");t.map=b.getUniformLocation(n,"map");t.occlusionMap=b.getUniformLocation(n,"occlusionMap");t.opacity=
+b.getUniformLocation(n,"opacity");t.color=b.getUniformLocation(n,"color");t.scale=b.getUniformLocation(n,"scale");t.rotation=b.getUniformLocation(n,"rotation");t.screenPosition=b.getUniformLocation(n,"screenPosition")};this.render=function(a,d,e,f){var a=a.__webglFlares,s=a.length;if(s){var v=new THREE.Vector3,z=f/e,G=0.5*e,N=0.5*f,C=16/f,B=new THREE.Vector2(C*z,C),x=new THREE.Vector3(1,1,0),F=new THREE.Vector2(1,1),L=t,C=p;b.useProgram(n);b.enableVertexAttribArray(p.vertex);b.enableVertexAttribArray(p.uv);
+b.uniform1i(L.occlusionMap,0);b.uniform1i(L.map,1);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(C.vertex,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(C.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.disable(b.CULL_FACE);b.depthMask(!1);var w,E,y,D,H;for(w=0;wB;B++)z[B]=new THREE.Vector3,s[B]=new THREE.Vector3;z=G.shadowCascadeNearZ[v];G=G.shadowCascadeFarZ[v];s[0].set(-1,-1,z);s[1].set(1,-1,z);s[2].set(-1,
+1,z);s[3].set(1,1,z);s[4].set(-1,-1,G);s[5].set(1,-1,G);s[6].set(-1,1,G);s[7].set(1,1,G);C.originalCamera=p;s=new THREE.Gyroscope;s.position=m.shadowCascadeOffset;s.add(C);s.add(C.target);p.add(s);m.shadowCascadeArray[u]=C;console.log("Created virtualLight",C)}v=m;z=u;G=v.shadowCascadeArray[z];G.position.copy(v.position);G.target.position.copy(v.target.position);G.lookAt(G.target);G.shadowCameraVisible=v.shadowCameraVisible;G.shadowDarkness=v.shadowDarkness;G.shadowBias=v.shadowCascadeBias[z];s=v.shadowCascadeNearZ[z];
+v=v.shadowCascadeFarZ[z];G=G.pointsFrustum;G[0].z=s;G[1].z=s;G[2].z=s;G[3].z=s;G[4].z=v;G[5].z=v;G[6].z=v;G[7].z=v;N[q]=C;q++}else N[q]=m,q++;t=0;for(r=N.length;tv;v++)z=G[v],z.copy(s[v]),THREE.ShadowMapPlugin.__projector.unprojectVector(z,u),z.applyMatrix4(q.matrixWorldInverse),z.xk.x&&(k.x=z.x),z.yk.y&&(k.y=z.y),z.zk.z&&
+(k.z=z.z);q.left=i.x;q.right=k.x;q.top=k.y;q.bottom=i.y;q.updateProjectionMatrix()}q=m.shadowMap;s=m.shadowMatrix;u=m.shadowCamera;u.position.setFromMatrixPosition(m.matrixWorld);l.setFromMatrixPosition(m.target.matrixWorld);u.lookAt(l);u.updateMatrixWorld();u.matrixWorldInverse.getInverse(u.matrixWorld);m.cameraHelper&&(m.cameraHelper.visible=m.shadowCameraVisible);m.shadowCameraVisible&&m.cameraHelper.update();s.set(0.5,0,0,0.5,0,0.5,0,0.5,0,0,0.5,0.5,0,0,0,1);s.multiply(u.projectionMatrix);s.multiply(u.matrixWorldInverse);
+h.multiplyMatrices(u.projectionMatrix,u.matrixWorldInverse);g.setFromMatrix(h);b.setRenderTarget(q);b.clear();G=n.__webglObjects;m=0;for(q=G.length;m 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}"].join("\n"));
+s.compileShader(L);s.compileShader(w);s.attachShader(u,L);s.attachShader(u,w);s.linkProgram(u);x=u;m=s.getAttribLocation(x,"position");q=s.getAttribLocation(x,"uv");a=s.getUniformLocation(x,"uvOffset");b=s.getUniformLocation(x,"uvScale");c=s.getUniformLocation(x,"rotation");d=s.getUniformLocation(x,"scale");e=s.getUniformLocation(x,"color");f=s.getUniformLocation(x,"map");g=s.getUniformLocation(x,"opacity");h=s.getUniformLocation(x,"modelViewMatrix");i=s.getUniformLocation(x,"projectionMatrix");k=
+s.getUniformLocation(x,"fogType");l=s.getUniformLocation(x,"fogDensity");n=s.getUniformLocation(x,"fogNear");p=s.getUniformLocation(x,"fogFar");t=s.getUniformLocation(x,"fogColor");r=s.getUniformLocation(x,"alphaTest");u=document.createElement("canvas");u.width=8;u.height=8;L=u.getContext("2d");L.fillStyle="#ffffff";L.fillRect(0,0,u.width,u.height);z=new THREE.Texture(u);z.needsUpdate=!0};this.render=function(F,G){var w=F.__webglSprites,E=w.length;if(E){s.useProgram(x);s.enableVertexAttribArray(m);
+s.enableVertexAttribArray(q);s.disable(s.CULL_FACE);s.enable(s.BLEND);s.bindBuffer(s.ARRAY_BUFFER,C);s.vertexAttribPointer(m,2,s.FLOAT,!1,16,0);s.vertexAttribPointer(q,2,s.FLOAT,!1,16,8);s.bindBuffer(s.ELEMENT_ARRAY_BUFFER,B);s.uniformMatrix4fv(i,!1,G.projectionMatrix.elements);s.activeTexture(s.TEXTURE0);s.uniform1i(f,0);var y=0,D=0,H=F.fog;H?(s.uniform3f(t,H.color.r,H.color.g,H.color.b),H instanceof THREE.Fog?(s.uniform1f(n,H.near),s.uniform1f(p,H.far),s.uniform1i(k,1),D=y=1):H instanceof THREE.FogExp2&&
+(s.uniform1f(l,H.density),s.uniform1i(k,2),D=y=2)):(s.uniform1i(k,0),D=y=0);for(var K,A,N=[],H=0;H; Licensed MIT */
+
+/**
+ * @author alteredq / http://alteredqualia.com/
+ * @author mr.doob / http://mrdoob.com/
+ */
+
+var Detector = {
+
+ canvas: !! window.CanvasRenderingContext2D,
+ webgl: ( function () { try { var canvas = document.createElement( 'canvas' ); return !! window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); } catch( e ) { return false; } } )(),
+ workers: !! window.Worker,
+ fileapi: window.File && window.FileReader && window.FileList && window.Blob,
+
+ getWebGLErrorMessage: function () {
+
+ var element = document.createElement( 'div' );
+ element.id = 'webgl-error-message';
+ element.style.fontFamily = 'monospace';
+ element.style.fontSize = '13px';
+ element.style.fontWeight = 'normal';
+ element.style.textAlign = 'center';
+ element.style.background = '#fff';
+ element.style.color = '#000';
+ element.style.padding = '1.5em';
+ element.style.width = '400px';
+ element.style.margin = '5em auto 0';
+
+ if ( ! this.webgl ) {
+
+ element.innerHTML = window.WebGLRenderingContext ? [
+ 'Your graphics card does not seem to support WebGL.
',
+ 'Find out how to get it here.'
+ ].join( '\n' ) : [
+ 'Your browser does not seem to support WebGL.
',
+ 'Find out how to get it here.'
+ ].join( '\n' );
+
+ }
+
+ return element;
+
+ },
+
+ addGetWebGLMessage: function ( parameters ) {
+
+ var parent, id, element;
+
+ parameters = parameters || {};
+
+ parent = parameters.parent !== undefined ? parameters.parent : document.body;
+ id = parameters.id !== undefined ? parameters.id : 'oldie';
+
+ element = Detector.getWebGLErrorMessage();
+ element.id = id;
+
+ parent.appendChild( element );
+
+ }
+
+};
+/*!
+ * Valiant360 panorama video player/photo viewer jquery plugin
+ *
+ * Copyright (c) 2014 Charlie Hoey <@flimshaw>
+ *
+ * Released under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Jquery plugin pattern based on https://github.com/jquery-boilerplate/jquery-patterns/blob/master/patterns/jquery.basic.plugin-boilerplate.js
+ */
+
+/* REQUIREMENTS:
+
+jQuery 1.7.2 or greater
+three.js r65 or higher
+
+*/
+
+
+/*!
+ * jQuery lightweight plugin boilerplate
+ * Original author: @ajpiano
+ * Further changes, comments: @addyosmani
+ * Licensed under the MIT license
+ */
+
+// the semi-colon before the function invocation is a safety
+// net against concatenated scripts and/or other plugins
+// that are not closed properly.
+;(function ( $, THREE, Detector, window, document, undefined ) {
+
+ // undefined is used here as the undefined global
+ // variable in ECMAScript 3 and is mutable (i.e. it can
+ // be changed by someone else). undefined isn't really
+ // being passed in so we can ensure that its value is
+ // truly undefined. In ES5, undefined can no longer be
+ // modified.
+
+ // window and document are passed through as local
+ // variables rather than as globals, because this (slightly)
+ // quickens the resolution process and can be more
+ // efficiently minified (especially when both are
+ // regularly referenced in your plugin).
+
+ // Create the defaults once
+ var pluginName = "Valiant360",
+ plugin, // will hold reference to instantiated Plugin
+ defaults = {
+ crossOrigin: 'anonymous',
+ clickAndDrag: false,
+ keyboardControls: true,
+ fov: 35,
+ fovMin: 3,
+ fovMax: 100,
+ hideControls: false,
+ lon: 0,
+ lat: 0,
+ loop: "loop",
+ muted: true,
+ volume: 0.5,
+ debug: false,
+ flatProjection: false,
+ autoplay: true
+ };
+
+ // The actual plugin constructor
+ function Plugin( element, options ) {
+ this.element = element;
+
+ // jQuery has an extend method that merges the
+ // contents of two or more objects, storing the
+ // result in the first object. The first object
+ // is generally empty because we don't want to alter
+ // the default options for future instances of the plugin
+ this.options = $.extend( {}, defaults, options) ;
+
+ this._defaults = defaults;
+ this._name = pluginName;
+
+ this.init();
+ }
+
+ Plugin.prototype = {
+
+ init: function() {
+ // Place initialization logic here
+ // You already have access to the DOM element and
+ // the options via the instance, e.g. this.element
+ // and this.options
+ // you can add more functions like the one below and
+ // call them like so: this.yourOtherFunction(this.element, this.options).
+
+ // instantiate some local variables we're going to need
+ this._time = new Date().getTime();
+ this._controls = {};
+ this._id = this.generateUUID();
+
+ this._requestAnimationId = ''; // used to cancel requestAnimationFrame on destroy
+ this._isVideo = false;
+ this._isPhoto = false;
+ this._isFullscreen = false;
+ this._mouseDown = false;
+ this._dragStart = {};
+
+ this._lat = this.options.lat;
+ this._lon = this.options.lon;
+ this._fov = this.options.fov;
+
+ // save our original height and width for returning from fullscreen
+ this._originalWidth = $(this.element).find('canvas').width();
+ this._originalHeight = $(this.element).find('canvas').height();
+
+ // add a class to our element so it inherits the appropriate styles
+ $(this.element).addClass('Valiant360_default');
+
+ // add tabindex attribute to enable the focus on the element (required for keyboard controls)
+ if(this.options.keyboardControls && !$(this.element).attr("tabindex")){
+ $(this.element).attr("tabindex", "1");
+ }
+
+ this.createMediaPlayer();
+ this.createControls();
+
+ },
+
+ generateUUID: function(){
+ var d = new Date().getTime();
+ var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = (d + Math.random()*16)%16 | 0;
+ d = Math.floor(d/16);
+ return (c==='x' ? r : (r&0x7|0x8)).toString(16);
+ });
+ return uuid;
+ },
+
+ createMediaPlayer: function() {
+
+ // make a self reference we can pass to our callbacks
+ var self = this;
+
+ // create a local THREE.js scene
+ this._scene = new THREE.Scene();
+
+ // create ThreeJS camera
+ this._camera = new THREE.PerspectiveCamera(this._fov, $(this.element).width() / $(this.element).height(), 0.1, 1000);
+ this._camera.setLens(this._fov);
+
+ // create ThreeJS renderer and append it to our object
+ this._renderer = Detector.webgl? new THREE.WebGLRenderer(): new THREE.CanvasRenderer();
+ this._renderer.setSize( $(this.element).width(), $(this.element).height() );
+ this._renderer.autoClear = false;
+ this._renderer.setClearColor( 0x333333, 1 );
+
+ // append the rendering element to this div
+ $(this.element).append(this._renderer.domElement);
+
+ var createAnimation = function () {
+ self._texture.generateMipmaps = false;
+ self._texture.minFilter = THREE.LinearFilter;
+ self._texture.magFilter = THREE.LinearFilter;
+ self._texture.format = THREE.RGBFormat;
+
+ // create ThreeJS mesh sphere onto which our texture will be drawn
+ self._mesh = new THREE.Mesh( new THREE.SphereGeometry( 500, 80, 50 ), new THREE.MeshBasicMaterial( { map: self._texture } ) );
+ self._mesh.scale.x = -1; // mirror the texture, since we're looking from the inside out
+ self._scene.add(self._mesh);
+
+ self.animate();
+ };
+
+ // figure out our texturing situation, based on what our source is
+ if( $(this.element).attr('data-photo-src') ) {
+ this._isPhoto = true;
+ THREE.ImageUtils.crossOrigin = this.options.crossOrigin;
+ this._texture = THREE.ImageUtils.loadTexture( $(this.element).attr('data-photo-src') );
+ createAnimation();
+ } else {
+ this._isVideo = true;
+
+ // create loading overlay
+ var loadingHTML = '';
+ $(this.element).append(loadingHTML);
+ this.showWaiting();
+
+ // create off-dom video player
+ this._video = document.createElement( 'video' );
+ this._video.setAttribute('crossorigin', this.options.crossOrigin);
+ this._video.style.display = 'none';
+ $(this.element).append( this._video );
+ this._video.loop = this.options.loop;
+ this._video.muted = this.options.muted;
+ this._video.volume = this.options.volume;
+
+ // attach video player event listeners
+ this._video.addEventListener("ended", function() {
+
+ });
+
+ // Progress Meter
+ this._video.addEventListener("progress", function() {
+ var percent = null;
+ if (self._video && self._video.buffered && self._video.buffered.length > 0 && self._video.buffered.end && self._video.duration) {
+ percent = self._video.buffered.end(0) / self._video.duration;
+ }
+ // Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
+ // to be anything other than 0. If the byte count is available we use this instead.
+ // Browsers that support the else if do not seem to have the bufferedBytes value and
+ // should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8.
+ else if (self._video && self._video.bytesTotal !== undefined && self._video.bytesTotal > 0 && self._video.bufferedBytes !== undefined) {
+ percent = self._video.bufferedBytes / self._video.bytesTotal;
+ }
+
+ // Someday we can have a loading animation for videos
+ var cpct = Math.round(percent * 100);
+ if(cpct === 100) {
+ // do something now that we are done
+ } else {
+ // do something with this percentage info (cpct)
+ }
+ });
+ // Error listener
+ this._video.addEventListener('error', function (event) {
+ console.error(self._video.error);
+ self.showError();
+ });
+
+ this._video.addEventListener("timeupdate", function() {
+ if (this.paused === false){
+ var percent = this.currentTime * 100 / this.duration;
+ $(self.element).find('.controlsWrapper > .valiant-progress-bar')[0].children[0].setAttribute("style", "width:" + percent + "%;");
+ $(self.element).find('.controlsWrapper > .valiant-progress-bar')[0].children[1].setAttribute("style", "width:" + (100 - percent) + "%;");
+ //Update time label
+ var durMin = Math.floor(this.duration / 60);
+ var durSec = Math.floor(this.duration - (durMin * 60));
+ var timeMin = Math.floor(this.currentTime / 60);
+ var timeSec = Math.floor(this.currentTime - (timeMin * 60));
+ var duration = durMin + ':' + (durSec < 10 ? '0' + durSec : durSec);
+ var currentTime = timeMin + ':' + (timeSec < 10 ? '0' + timeSec : timeSec);
+ $(self.element).find('.controls .timeLabel').html(currentTime+' / '+duration);
+ }
+ });
+
+ // IE 11 and previous not supports THREE.Texture([video]), we must create a canvas that draws the video and use that to create the Texture
+ var isIE = navigator.appName == 'Microsoft Internet Explorer' || !!(navigator.userAgent.match(/Trident/) || navigator.userAgent.match(/rv 11/));
+ if (isIE) {
+ this._videocanvas = document.createElement('canvas');
+ this._texture = new THREE.Texture(this._videocanvas);
+ // set canvas size = video size when known
+ this._video.addEventListener('loadedmetadata', function () {
+ self._videocanvas.width = self._video.videoWidth;
+ self._videocanvas.height = self._video.videoHeight;
+ createAnimation();
+ });
+ }else{
+ this._texture = new THREE.Texture( this._video );
+ }
+
+ //force browser caching of the video to solve rendering errors with big videos
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', $(this.element).attr('data-video-src'), true);
+ xhr.responseType = 'blob';
+ xhr.onload = function (e) {
+ if (this.status === 200) {
+ var vid = (window.webkitURL ? webkitURL : URL).createObjectURL(this.response);
+ //Video Play Listener, fires after video loads
+ $(self._video).bind("canplaythrough", function () {
+ if (self.options.autoplay === true) {
+ self.hideWaiting();
+ self.play();
+ self._videoReady = true;
+ }
+ });
+
+ // set the video src and begin loading
+ self._video.src = vid;
+ }
+ };
+ xhr.onreadystatechange = function (oEvent) {
+ if (xhr.readyState === 4) {
+ if (xhr.status !== 200) {
+ console.error('Video error: status ' + xhr.status);
+ self.showError();
+ }
+ }
+ };
+ xhr.send();
+
+ if(!isIE){
+ createAnimation();
+ }
+ }
+ },
+
+ // creates div and buttons for onscreen video controls
+ createControls: function() {
+
+ var muteControl = this.options.muted ? 'fa-volume-off' : 'fa-volume-up';
+ var playPauseControl = this.options.autoplay ? 'fa-pause' : 'fa-play';
+
+ var controlsHTML = ' \
+ \
+ ';
+
+ $(this.element).append(controlsHTML, true);
+ $(this.element).append('00:00
', true);
+
+ // hide controls if option is set
+ if(this.options.hideControls) {
+ $(this.element).find('.controls').hide();
+ }
+
+ // wire up controller events to dom elements
+ this.attachControlEvents();
+ },
+
+ attachControlEvents: function() {
+
+ // create a self var to pass to our controller functions
+ var self = this;
+
+ this.element.addEventListener( 'mousemove', this.onMouseMove.bind(this), false );
+ this.element.addEventListener( 'touchmove', this.onMouseMove.bind(this), false );
+ this.element.addEventListener( 'mousewheel', this.onMouseWheel.bind(this), false );
+ this.element.addEventListener( 'DOMMouseScroll', this.onMouseWheel.bind(this), false );
+ this.element.addEventListener( 'mousedown', this.onMouseDown.bind(this), false);
+ this.element.addEventListener( 'touchstart', this.onMouseDown.bind(this), false);
+ this.element.addEventListener( 'mouseup', this.onMouseUp.bind(this), false);
+ this.element.addEventListener( 'touchend', this.onMouseUp.bind(this), false);
+
+ if(this.options.keyboardControls){
+ this.element.addEventListener('keydown',this.onKeyDown.bind(this), false);
+ this.element.addEventListener('keyup',this.onKeyUp.bind(this), false);
+ // Used custom press event because for the arrow buttons is not throws the 'keypress' event
+ this.element.addEventListener('keyArrowPress',this.onKeyArrowPress.bind(this), false);
+ this.element.addEventListener('click',function () {
+ $(self.element).focus();
+ },false);
+ }
+
+ $(self.element).find('.controlsWrapper > .valiant-progress-bar')[0].addEventListener("click", this.onProgressClick.bind(this), false);
+ $(self.element).find('.controlsWrapper > .valiant-progress-bar')[0].addEventListener("mousemove", this.onProgressMouseMove.bind(this), false);
+ $(self.element).find('.controlsWrapper > .valiant-progress-bar')[0].addEventListener("mouseout", this.onProgressMouseOut.bind(this), false);
+
+ $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange',this.fullscreen.bind(this));
+
+ $(window).resize(function() {
+ self.resizeGL($(self.element).width(), $(self.element).height());
+ });
+
+ // Player Controls
+ $(this.element).find('.playButton').click(function(e) {
+ e.preventDefault();
+ if($(this).hasClass('fa-pause')) {
+ $(this).removeClass('fa-pause').addClass('fa-play');
+ self.pause();
+ } else {
+ $(this).removeClass('fa-play').addClass('fa-pause');
+ self.play();
+ }
+ });
+
+ $(this.element).find(".fullscreenButton").click(function(e) {
+ e.preventDefault();
+ var elem = $(self.element)[0];
+ if($(this).hasClass('fa-expand')) {
+ if (elem.requestFullscreen) {
+ elem.requestFullscreen();
+ } else if (elem.msRequestFullscreen) {
+ elem.msRequestFullscreen();
+ } else if (elem.mozRequestFullScreen) {
+ elem.mozRequestFullScreen();
+ } else if (elem.webkitRequestFullscreen) {
+ elem.webkitRequestFullscreen();
+ }
+ } else {
+ if (elem.requestFullscreen) {
+ document.exitFullscreen();
+ } else if (elem.msRequestFullscreen) {
+ document.msExitFullscreen();
+ } else if (elem.mozRequestFullScreen) {
+ document.mozCancelFullScreen();
+ } else if (elem.webkitRequestFullscreen) {
+ document.webkitExitFullscreen();
+ }
+ }
+ });
+
+ $(this.element).find(".muteButton").click(function(e) {
+ e.preventDefault();
+ if($(this).hasClass('fa-volume-off')) {
+ $(this).removeClass('fa-volume-off').addClass('fa-volume-up');
+ self._video.muted = false;
+ } else {
+ $(this).removeClass('fa-volume-up').addClass('fa-volume-off');
+ self._video.muted = true;
+ }
+ });
+
+ $(this.element).find('.controlsWrapper .volumeControl')
+ .mousedown(this.onVolumeMouseDown.bind(this))
+ .mouseup(this.onVolumeMouseUp.bind(this))
+ .mouseleave(this.onVolumeMouseUp.bind(this))
+ .mousemove(this.onVolumeMouseMove.bind(this));
+
+ $(this._video).on('volumechange',this.onVolumeChange.bind(this));
+ },
+
+ onMouseMove: function(event) {
+ this._onPointerDownPointerX = event.clientX;
+ this._onPointerDownPointerY = -event.clientY;
+
+ this.relativeX = event.pageX - $(this.element).find('canvas').offset().left;
+
+ this._onPointerDownLon = this._lon;
+ this._onPointerDownLat = this._lat;
+
+ var x, y;
+
+ if(this.options.clickAndDrag) {
+ if(this._mouseDown) {
+ x = event.pageX - this._dragStart.x;
+ y = event.pageY - this._dragStart.y;
+ this._dragStart.x = event.pageX;
+ this._dragStart.y = event.pageY;
+ this._lon += x;
+ this._lat -= y;
+ }
+ } else {
+ x = event.pageX - $(this.element).find('canvas').offset().left;
+ y = event.pageY - $(this.element).find('canvas').offset().top;
+ this._lon = ( x / $(this.element).find('canvas').width() ) * 430 - 225;
+ this._lat = ( y / $(this.element).find('canvas').height() ) * -180 + 90;
+ }
+ },
+
+ onMouseWheel: function(event) {
+
+ var wheelSpeed = -0.01;
+
+ // WebKit
+ if ( event.wheelDeltaY ) {
+ this._fov -= event.wheelDeltaY * wheelSpeed;
+ // Opera / Explorer 9
+ } else if ( event.wheelDelta ) {
+ this._fov -= event.wheelDelta * wheelSpeed;
+ // Firefox
+ } else if ( event.detail ) {
+ this._fov += event.detail * 1.0;
+ }
+
+ if(this._fov < this.options.fovMin) {
+ this._fov = this.options.fovMin;
+ } else if(this._fov > this.options.fovMax) {
+ this._fov = this.options.fovMax;
+ }
+
+ this._camera.setLens(this._fov);
+ event.preventDefault();
+ },
+
+ onMouseDown: function(event) {
+ this._mouseDown = true;
+ this._dragStart.x = event.pageX;
+ this._dragStart.y = event.pageY;
+ },
+
+ onProgressClick: function(event) {
+ if(this._isVideo && this._video.readyState === this._video.HAVE_ENOUGH_DATA) {
+ var percent = this.relativeX / $(this.element).find('canvas').width() * 100;
+ $(this.element).find('.controlsWrapper > .valiant-progress-bar')[0].children[0].setAttribute("style", "width:" + percent + "%;");
+ $(this.element).find('.controlsWrapper > .valiant-progress-bar')[0].children[1].setAttribute("style", "width:" + (100 - percent) + "%;");
+ this._video.currentTime = this._video.duration * percent / 100;
+ }
+ },
+
+ onProgressMouseMove: function(event){
+ var percent = this.relativeX / $(this.element).find('canvas').width() * 100;
+ if(percent){
+ var tooltip = $(this.element).find('.timeTooltip');
+ var tooltipLeft = (this.relativeX - (tooltip.width()/2));
+ tooltipLeft = tooltipLeft <0? 0:Math.min(tooltipLeft,$(this.element).find('canvas').width() - tooltip.outerWidth());
+ tooltip.css({ left: tooltipLeft + 'px' });
+ tooltip.show();
+ var time = (percent / 100) * this._video.duration;
+ var timeMin = Math.floor(time / 60);
+ var timeSec = Math.floor(time - (timeMin * 60));
+ tooltip.html(timeMin + ':' + (timeSec < 10 ? '0' + timeSec : timeSec));
+ }
+ },
+
+ onProgressMouseOut: function (event) {
+ $(this.element).find('.timeTooltip').hide();
+ },
+
+ onMouseUp: function(event) {
+ this._mouseDown = false;
+ },
+
+ onKeyDown: function(event) {
+ var keyCode = event.keyCode;
+ if (keyCode >= 37 && keyCode <= 40) {
+ event.preventDefault();
+ this._keydown = true;
+ var pressEvent = document.createEvent('CustomEvent');
+ pressEvent.initCustomEvent("keyArrowPress",true,true,{'keyCode':keyCode});
+ this.element.dispatchEvent(pressEvent);
+ }
+ },
+
+ onKeyUp: function (event) {
+ var keyCode = event.keyCode;
+ if (keyCode >= 37 && keyCode <= 40) {
+ event.preventDefault();
+ this._keydown = false;
+ }
+ },
+
+ onKeyArrowPress: function (event) {
+ if (this._keydown) {
+ var keyCode = event.detail? event.detail.keyCode:null;
+ var offset = 3;
+ var pressDelay = 50;
+ var element = this.element;
+ event.preventDefault();
+ switch (keyCode) {
+ //Arrow left
+ case 37: this._lon -= offset;
+ break;
+ //Arrow right
+ case 39: this._lon += offset;
+ break;
+ //Arrow up
+ case 38: this._lat += offset;
+ break;
+ //Arrow down
+ case 40: this._lat -= offset;
+ break;
+ }
+ setTimeout(function () {
+ var pressEvent = document.createEvent('CustomEvent');
+ pressEvent.initCustomEvent("keyArrowPress",true,true,{'keyCode':keyCode});
+ element.dispatchEvent(pressEvent);
+ },
+ pressDelay);
+ }
+ },
+
+ onVolumeMouseDown: function(event){
+ event.preventDefault();
+ this._volumeMouseDown = true;
+ this.onVolumeMouseMove(event);
+ },
+
+ onVolumeMouseUp: function(event){
+ event.preventDefault();
+ this._volumeMouseDown = false;
+ },
+
+ onVolumeMouseMove: function(event){
+ event.preventDefault();
+ if(this._volumeMouseDown){
+ var volumeControl = $(this.element).find('.controlsWrapper .volumeControl');
+ var percent = (this.relativeX - volumeControl.offset().left + (volumeControl.find('.volumeBar > .volumeCursor').width()/2)) / volumeControl.width() * 100;
+ if(percent>=0 && percent<=100){
+ this._video.volume = percent/100;
+ }
+ }
+ },
+
+ onVolumeChange: function(event){
+ //change volume cursor value
+ var percent = this._video.muted==true && !this._volumeMouseDown? 0:(this._video.volume * 100);
+ $(this.element).find('.controlsWrapper .volumeControl > .volumeBar').css({width: percent+"%"});
+
+ //change mute button
+ var muteButton = $(this.element).find(".muteButton");
+ if((percent>0 && muteButton.hasClass('fa-volume-off')) || (percent==0 && muteButton.hasClass('fa-volume-up'))){
+ muteButton.click();
+ }
+ },
+
+ animate: function() {
+ // set our animate function to fire next time a frame is ready
+ this._requestAnimationId = requestAnimationFrame( this.animate.bind(this) );
+
+ if( this._isVideo ) {
+ if ( this._video.readyState === this._video.HAVE_ENOUGH_DATA) {
+ if(this._videocanvas) {
+ this._videocanvas.getContext('2d').drawImage(this._video, 0, 0, this._videocanvas.width, this._videocanvas.height);
+ }
+ if(typeof(this._texture) !== "undefined" ) {
+ var ct = new Date().getTime();
+ if(ct - this._time >= 30) {
+ this._texture.needsUpdate = true;
+ this._time = ct;
+ }
+ }
+ }
+ }
+
+ this.render();
+ },
+
+ render: function() {
+ this._lat = Math.max( - 85, Math.min( 85, this._lat ) );
+ this._phi = ( 90 - this._lat ) * Math.PI / 180;
+ this._theta = this._lon * Math.PI / 180;
+
+ var cx = 500 * Math.sin( this._phi ) * Math.cos( this._theta );
+ var cy = 500 * Math.cos( this._phi );
+ var cz = 500 * Math.sin( this._phi ) * Math.sin( this._theta );
+
+ this._camera.lookAt(new THREE.Vector3(cx, cy, cz));
+
+ // distortion
+ if(this.options.flatProjection) {
+ this._camera.position.x = 0;
+ this._camera.position.y = 0;
+ this._camera.position.z = 0;
+ } else {
+ this._camera.position.x = - cx;
+ this._camera.position.y = - cy;
+ this._camera.position.z = - cz;
+ }
+
+ this._renderer.clear();
+ this._renderer.render( this._scene, this._camera );
+ },
+
+ // Video specific functions, exposed to controller
+ play: function() {
+ //code to play media
+ this._video.play();
+ },
+
+ pause: function() {
+ //code to stop media
+ this._video.pause();
+ },
+
+ loadVideo: function(videoFile) {
+ this._video.src = videoFile;
+ },
+ unloadVideo: function() {
+ // overkill unloading to avoid dreaded video 'pending' bug in Chrome. See https://code.google.com/p/chromium/issues/detail?id=234779
+ this.pause();
+ this._video.src = '';
+ this._video.removeAttribute('src');
+ },
+ loadPhoto: function(photoFile) {
+ this._texture = THREE.ImageUtils.loadTexture( photoFile );
+ },
+
+ fullscreen: function() {
+ if($(this.element).find('a.fa-expand').length > 0) {
+ this.resizeGL(screen.width, screen.height);
+
+ $(this.element).addClass('fullscreen');
+ $(this.element).find('a.fa-expand').removeClass('fa-expand').addClass('fa-compress');
+
+ this._isFullscreen = true;
+ } else {
+ this.resizeGL(this._originalWidth, this._originalHeight);
+
+ $(this.element).removeClass('fullscreen');
+ $(this.element).find('a.fa-compress').removeClass('fa-compress').addClass('fa-expand');
+
+ this._isFullscreen = false;
+ }
+ },
+
+ resizeGL: function(w, h) {
+ this._renderer.setSize(w, h);
+ this._camera.aspect = w / h;
+ this._camera.updateProjectionMatrix();
+ },
+
+ showWaiting: function () {
+ var loading = $(this.element).find('.loading');
+ loading.find('.waiting-icon').show();
+ loading.find('.error-icon').hide();
+ loading.show();
+ },
+
+ hideWaiting: function () {
+ $(this.element).find('.loading').hide();
+ },
+
+ showError: function () {
+ var loading = $(this.element).find('.loading');
+ loading.find('.waiting-icon').hide();
+ loading.find('.error-icon').show();
+ loading.show();
+ },
+
+ destroy: function() {
+ window.cancelAnimationFrame(this._requestAnimationId);
+ this._requestAnimationId = '';
+ this._texture.dispose();
+ this._scene.remove(this._mesh);
+ if(this._isVideo) {
+ this.unloadVideo();
+ }
+ $(this._renderer.domElement).remove();
+ }
+ };
+
+ $.fn[pluginName] = function ( options ) {
+ // use pluginArguments instead of this.each arguments, otherwise Valiant360('loadVideo', 'path/to/video') path argument will be missing
+ var pluginArguments = arguments;
+ return this.each(function () {
+ if(typeof options === 'object' || !options) {
+ // A really lightweight plugin wrapper around the constructor,
+ // preventing against multiple instantiations
+ this.plugin = new Plugin(this, options);
+ if (!$.data(this, "plugin_" + pluginName)) {
+ $.data(this, "plugin_" + pluginName, this.plugin);
+ }
+ } else if(this.plugin[options]) {
+ // Allows plugin methods to be called - use pluginArguments instead of this.each arguments
+ return this.plugin[options].apply(this.plugin, Array.prototype.slice.call(pluginArguments, 1))
+ }
+ });
+ };
+
+})( jQuery, THREE, Detector, window, document );
diff --git a/sigal/themes/galleria/static/valiant/vr.png b/sigal/themes/galleria/static/valiant/vr.png
new file mode 100644
index 0000000..29905ed
Binary files /dev/null and b/sigal/themes/galleria/static/valiant/vr.png differ
diff --git a/sigal/themes/galleria/templates/album.html b/sigal/themes/galleria/templates/album.html
index 3187519..4e351dd 100644
--- a/sigal/themes/galleria/templates/album.html
+++ b/sigal/themes/galleria/templates/album.html
@@ -22,6 +22,11 @@
+
+
+

+
{% if album.zip %}
@@ -71,6 +76,48 @@
+
+
+
+
+
+