f;f++){a.__webglFramebuffer[f]=
-m.createFramebuffer();a.__webglRenderbuffer[f]=m.createRenderbuffer();m.texImage2D(m.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=m.TEXTURE_CUBE_MAP_POSITIVE_X+f;m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer[f]);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,h,g.__webglTexture,0);G(a.__webglRenderbuffer[f],a)}c&&m.generateMipmap(m.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=m.createFramebuffer(),a.__webglRenderbuffer=a.shareDepthFrom?a.shareDepthFrom.__webglRenderbuffer:
-m.createRenderbuffer(),m.bindTexture(m.TEXTURE_2D,a.__webglTexture),A(m.TEXTURE_2D,a,c),m.texImage2D(m.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=m.TEXTURE_2D,m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,d,a.__webglTexture,0),a.shareDepthFrom?a.depthBuffer&&!a.stencilBuffer?m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):a.depthBuffer&&a.stencilBuffer&&m.framebufferRenderbuffer(m.FRAMEBUFFER,
-m.DEPTH_STENCIL_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):G(a.__webglRenderbuffer,a),c&&m.generateMipmap(m.TEXTURE_2D);b?m.bindTexture(m.TEXTURE_CUBE_MAP,null):m.bindTexture(m.TEXTURE_2D,null);m.bindRenderbuffer(m.RENDERBUFFER,null);m.bindFramebuffer(m.FRAMEBUFFER,null)}a?(b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=pb,a=qb,d=ib,e=bb);b!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,b),m.viewport(d,e,c,a),ab=b);Xb=c;fc=a};this.readRenderTargetPixels=
-function(a,b,c,d,e,f){if(!(a instanceof THREE.WebGLRenderTarget))console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");else if(a.__webglFramebuffer)if(a.format!==THREE.RGBAFormat)console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA format. readPixels can read only RGBA format.");else{var g=!1;a.__webglFramebuffer!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),g=!0);m.checkFramebufferStatus(m.FRAMEBUFFER)===
-m.FRAMEBUFFER_COMPLETE?m.readPixels(b,c,d,e,m.RGBA,m.UNSIGNED_BYTE,f):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.");g&&m.bindFramebuffer(m.FRAMEBUFFER,ab)}};this.initMaterial=function(){THREE.warn("THREE.WebGLRenderer: .initMaterial() has been removed.")};this.addPrePlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.")};this.addPostPlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.")};
-this.updateShadowMap=function(){THREE.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.")}};
+a.positionArray,m.DYNAMIC_DRAW),W.enableAttribute(b.attributes.position),m.vertexAttribPointer(b.attributes.position,3,m.FLOAT,!1,0,0));if(a.hasNormals){m.bindBuffer(m.ARRAY_BUFFER,a.__webglNormalBuffer);if(!1===c instanceof THREE.MeshPhongMaterial&&c.shading===THREE.FlatShading){var d,e,f,g,h,k,n,l,p,q,r,s=3*a.count;for(r=0;r f;f++){a.__webglFramebuffer[f]=m.createFramebuffer();a.__webglRenderbuffer[f]=m.createRenderbuffer();m.texImage2D(m.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=m.TEXTURE_CUBE_MAP_POSITIVE_X+f;m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer[f]);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,
+h,g.__webglTexture,0);G(a.__webglRenderbuffer[f],a)}c&&m.generateMipmap(m.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=m.createFramebuffer(),a.__webglRenderbuffer=a.shareDepthFrom?a.shareDepthFrom.__webglRenderbuffer:m.createRenderbuffer(),m.bindTexture(m.TEXTURE_2D,a.__webglTexture),A(m.TEXTURE_2D,a,c),m.texImage2D(m.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=m.TEXTURE_2D,m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,d,a.__webglTexture,
+0),a.shareDepthFrom?a.depthBuffer&&!a.stencilBuffer?m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):a.depthBuffer&&a.stencilBuffer&&m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_STENCIL_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):G(a.__webglRenderbuffer,a),c&&m.generateMipmap(m.TEXTURE_2D);b?m.bindTexture(m.TEXTURE_CUBE_MAP,null):m.bindTexture(m.TEXTURE_2D,null);m.bindRenderbuffer(m.RENDERBUFFER,null);m.bindFramebuffer(m.FRAMEBUFFER,null)}a?
+(b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=pb,a=qb,d=ib,e=bb);b!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,b),m.viewport(d,e,c,a),ab=b);Xb=c;fc=a};this.readRenderTargetPixels=function(a,b,c,d,e,f){if(!(a instanceof THREE.WebGLRenderTarget))console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");else if(a.__webglFramebuffer)if(a.format!==THREE.RGBAFormat)console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA format. readPixels can read only RGBA format.");
+else{var g=!1;a.__webglFramebuffer!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),g=!0);m.checkFramebufferStatus(m.FRAMEBUFFER)===m.FRAMEBUFFER_COMPLETE?m.readPixels(b,c,d,e,m.RGBA,m.UNSIGNED_BYTE,f):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.");g&&m.bindFramebuffer(m.FRAMEBUFFER,ab)}};this.initMaterial=function(){THREE.warn("THREE.WebGLRenderer: .initMaterial() has been removed.")};this.addPrePlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.")};
+this.addPostPlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.")};this.updateShadowMap=function(){THREE.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.")}};
THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=void 0!==c.wrapS?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==c.wrapT?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==c.magFilter?c.magFilter:THREE.LinearFilter;this.minFilter=void 0!==c.minFilter?c.minFilter:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==c.anisotropy?c.anisotropy:1;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=void 0!==c.format?c.format:
THREE.RGBAFormat;this.type=void 0!==c.type?c.type:THREE.UnsignedByteType;this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.generateMipmaps=!0;this.shareDepthFrom=void 0!==c.shareDepthFrom?c.shareDepthFrom:null};
THREE.WebGLRenderTarget.prototype={constructor:THREE.WebGLRenderTarget,setSize:function(a,b){this.width=a;this.height=b},clone:function(){var a=new THREE.WebGLRenderTarget(this.width,this.height);a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.format=this.format;a.type=this.type;a.depthBuffer=this.depthBuffer;a.stencilBuffer=this.stencilBuffer;a.generateMipmaps=this.generateMipmaps;
@@ -577,50 +579,50 @@ THREE.WebGLExtensions=function(a){var b={};this.get=function(c){if(void 0!==b[c]
break;case "WEBGL_compressed_texture_pvrtc":d=a.getExtension("WEBGL_compressed_texture_pvrtc")||a.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;default:d=a.getExtension(c)}null===d&&THREE.warn("THREE.WebGLRenderer: "+c+" extension not supported.");return b[c]=d}};
THREE.WebGLProgram=function(){var a=0;return function(b,c,d,e){var f=b.context,g=d.defines,h=d.__webglShader.uniforms,k=d.attributes,l=d.__webglShader.vertexShader,p=d.__webglShader.fragmentShader,q=d.index0AttributeName;void 0===q&&!0===e.morphTargets&&(q="position");var n="SHADOWMAP_TYPE_BASIC";e.shadowMapType===THREE.PCFShadowMap?n="SHADOWMAP_TYPE_PCF":e.shadowMapType===THREE.PCFSoftShadowMap&&(n="SHADOWMAP_TYPE_PCF_SOFT");var t="ENVMAP_TYPE_CUBE",s="ENVMAP_MODE_REFLECTION",r="ENVMAP_BLENDING_MULTIPLY";
if(e.envMap){switch(d.envMap.mapping){case THREE.CubeReflectionMapping:case THREE.CubeRefractionMapping:t="ENVMAP_TYPE_CUBE";break;case THREE.EquirectangularReflectionMapping:case THREE.EquirectangularRefractionMapping:t="ENVMAP_TYPE_EQUIREC";break;case THREE.SphericalReflectionMapping:t="ENVMAP_TYPE_SPHERE"}switch(d.envMap.mapping){case THREE.CubeRefractionMapping:case THREE.EquirectangularRefractionMapping:s="ENVMAP_MODE_REFRACTION"}switch(d.combine){case THREE.MultiplyOperation:r="ENVMAP_BLENDING_MULTIPLY";
-break;case THREE.MixOperation:r="ENVMAP_BLENDING_MIX";break;case THREE.AddOperation:r="ENVMAP_BLENDING_ADD"}}var u=0h.length&&(console.warn("THREE.WebGLRenderer: Influences array is bigger than morphTargets array."),
+n.length=h.length);h=0;for(l=n.length;h[property:Camera camera]
Methods
- [method:todo update]()
+ [method:null update]()
[name]
Constructor
- [name]([DirectionalLight:todo light], [page:Number size])
+ [name]([page:DirectionalLight light], [page:Number size])
size -- dimensions of the plane
@@ -32,18 +32,18 @@ Properties
[property:Line lightPlane]
[property:DirectionalLight light]
[property:Line targetLine]
Methods
diff --git a/docs/api/extras/helpers/HemisphereLightHelper.html b/docs/api/extras/helpers/HemisphereLightHelper.html
index 52987be41530bd..070a2ae2735941 100644
--- a/docs/api/extras/helpers/HemisphereLightHelper.html
+++ b/docs/api/extras/helpers/HemisphereLightHelper.html
@@ -11,20 +11,18 @@
[name]
- Constructor
- [name]([page:todo light], [page:todo sphereSize], [page:todo arrowLength], [page:todo domeSize])
+ [name]([page:HemisphereLight light], [page:Number sphereSize])
- sphereSize -- todo
- arrowLength -- todo
- domeSize -- todo
+ light -- The HemisphereLight.
+ sphereSize -- The size of the sphere that shows the location.
Properties
[property:Mesh lightSphere]
[property:HemisphereLight light]
Methods
- [method:todo update]()
+ [method:null update]()
[name]
Constructor
[name]([page:Object parameters])
wireframe -- Render geometry as wireframe. Default is false (i.e. render as smooth shaded).
wireframeLinewidth -- Controls wireframe thickness. Default is 1.
morphTargets -- Define whether the material uses morphTargets. Default is false.
@@ -34,25 +33,19 @@ [name]([page:Object parameters])
Properties
- [property:number shading]
+ [property:boolean wireframe]
- Options are [page:Materials THREE.SmoothShading], [page:Materials THREE.FlatShading](default)
+ Render geometry as wireframe. Default is false (i.e. render as smooth shaded).
[property:boolean wireframe]
- [property:number wireframeLinewidth]
Due to limitations in the ANGLE layer, on Windows platforms linewidth will always be 1 regardless of the set value.
- [property:boolean morphTargets]
- Methods
diff --git a/docs/index.html b/docs/index.html
index b2d1624f909ffa..5b2f85dee1bb19 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -406,10 +406,10 @@ three.js / docs
if ( window.location.hash.length > 0 ) goToHash();
console.log([
- '_______ __',
- '/ _______\\/ __\\__ ____ _____ _____',
- '\\/__ __/ / /___\\/ ____\\/ _____\\/ _____\\',
- ' / / / / / _ / / __/ / __ / / __ /_ __ _____',
+ ' __ __',
+ ' __/ __\\ / __\\__ ____ _____ _____',
+ '/ __/ /\\/ / /___\\/ ____\\/ _____\\/ _____\\',
+ '\\/_ __/ / _ / / __/ / __ / / __ /_ __ _____',
'/ / / / / / / / / / / / ___/ / ___/\\ _\\/ __\\/ _____\\',
'\\/__/ \\/__/\\/__/\\/__/ \\/_____/\\/_____/\\/__/ / / / ___/',
' / __/ / \\__ \\',
diff --git a/editor/css/main.css b/editor/css/main.css
index 59d7904c66c9ed..8e4319c37717d1 100644
--- a/editor/css/main.css
+++ b/editor/css/main.css
@@ -67,6 +67,8 @@ textarea, input { outline: none; } /* osx */
display: none;
}
+/* CodeMirror */
+
.CodeMirror {
position: absolute !important;
@@ -76,6 +78,20 @@ textarea, input { outline: none; } /* osx */
}
+ .CodeMirror .errorLine {
+
+ background: rgba(255,0,0,0.25);
+
+ }
+
+ .CodeMirror .esprima-error {
+
+ color: #f00;
+ text-align: right;
+ padding: 0px 20px;
+
+ }
+
/* scene types */
.type {
diff --git a/editor/examples/arkanoid.app.json b/editor/examples/arkanoid.app.json
index b643cba08c2e34..0273a34e73a9e2 100755
--- a/editor/examples/arkanoid.app.json
+++ b/editor/examples/arkanoid.app.json
@@ -162,7 +162,7 @@
"31517222-A9A7-4EAF-B5F6-60751C0BABA3": [
{
"name": "Game Logic",
- "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = - 0.5;\ndirection.normalize();\n\nvar speed = new THREE.Vector3();\n\n//\n\nvar group = new THREE.Group();\nthis.add( group );\n\nvar paddle = this.getObjectByName( 'Paddle' );\ngroup.add( paddle );\n\nvar brick = this.getObjectByName( 'Brick' );\n\nfor ( var j = 0; j < 8; j ++ ) {\n\n\tvar material = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );\n\n\tfor ( var i = 0; i < 12; i ++ ) {\n\t\t\n\t\tvar object = brick.clone();\n\t\tobject.material = material;\n\t\tobject.position.x = i * 22 - 120;\n\t\tobject.position.z = j * 14 - 120;\n\t\tgroup.add( object );\n\t\t\n\t}\n\t\n}\n\nbrick.visible = false;\n\n//\n\nvar raycaster = new THREE.Raycaster();\n\nfunction update( event ) {\n\t\n\tif ( ball.position.x < - 150 || ball.position.x > 150 ) direction.x = - direction.x;\n\tif ( ball.position.z < - 200 || ball.position.z > 200 ) direction.z = - direction.z;\n\n\tball.position.add( speed.copy( direction ).multiplyScalar( event.delta / 4 ) );\n\t\n\traycaster.set( ball.position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( group.children );\n\t\n\tif ( intersections.length > 0 ) {\n\t\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 5 ) {\n\t\t\t\n\t\t\tif ( intersection.object !== paddle ) {\n\n\t\t\t\tgroup.remove( intersection.object );\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n}"
+ "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = - 0.5;\ndirection.normalize();\n\nvar speed = new THREE.Vector3();\n\n//\n\nvar group = new THREE.Group();\nthis.add( group );\n\nvar paddle = this.getObjectByName( 'Paddle' );\ngroup.add( paddle );\n\nvar brick = this.getObjectByName( 'Brick' );\n\nfor ( var j = 0; j < 8; j ++ ) {\n\n\tvar material = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );\n\n\tfor ( var i = 0; i < 12; i ++ ) {\n\t\t\n\t\tvar object = brick.clone();\n\t\tobject.material = material;\n\t\tobject.position.x = i * 22 - 120;\n\t\tobject.position.z = j * 14 - 120;\n\t\tgroup.add( object );\n\t\t\n\t}\n\t\n}\n\nbrick.visible = false;\n\n//\n\nvar raycaster = new THREE.Raycaster();\n\nfunction update( event ) {\n\t\n\tif ( ball.position.x < - 150 || ball.position.x > 150 ) direction.x = - direction.x;\n\tif ( ball.position.z < - 200 || ball.position.z > 200 ) direction.z = - direction.z;\n\n\tball.position.x = Math.max( - 150, Math.min( 150, ball.position.x ) );\n\tball.position.z = Math.max( - 200, Math.min( 200, ball.position.z ) );\n\t\n\tball.position.add( speed.copy( direction ).multiplyScalar( event.delta / 4 ) );\n\t\n\traycaster.set( ball.position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( group.children );\n\t\n\tif ( intersections.length > 0 ) {\n\t\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 5 ) {\n\t\t\t\n\t\t\tif ( intersection.object !== paddle ) {\n\n\t\t\t\tgroup.remove( intersection.object );\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n}"
}]
}
}
\ No newline at end of file
diff --git a/editor/examples/camera.app.json b/editor/examples/camera.app.json
old mode 100644
new mode 100755
index 1ff8d5252c4338..e4c7905d84db2c
--- a/editor/examples/camera.app.json
+++ b/editor/examples/camera.app.json
@@ -6,14 +6,14 @@
"generator": "ObjectExporter"
},
"object": {
- "uuid": "F0D8434F-4603-415B-8024-792FE97B9600",
+ "uuid": "C7FB195B-270E-47B4-95C9-1754652A9D11",
"type": "PerspectiveCamera",
"name": "Camera",
"fov": 50,
"aspect": 1.2252042007001167,
"near": 0.1,
"far": 100000,
- "matrix": [0.9700406789779663,-5.500052080442686e-10,-0.24294254183769226,0,-0.04822639003396034,0.9800989627838135,-0.19256223738193512,0,0.23810774087905884,0.19850945472717285,0.950735867023468,0,159.0158233642578,132.5708465576172,634.9312744140625,1]
+ "matrix": [0.9700406789779663,-2.851828329042405e-9,-0.24294254183769226,0,-0.04822639003396034,0.9800989627838135,-0.1925622522830963,0,0.23810774087905884,0.19850945472717285,0.950735867023468,0,154.7735595703125,129.03408813476562,617.992431640625,1]
}
},
"scene": {
@@ -23,6 +23,14 @@
"generator": "ObjectExporter"
},
"geometries": [
+ {
+ "uuid": "51BB3E54-D2DF-4576-9953-FB8E940588B5",
+ "type": "PlaneGeometry",
+ "width": 1000,
+ "height": 1000,
+ "widthSegments": 1,
+ "heightSegments": 1
+ },
{
"uuid": "D8E200D3-27BC-49F8-A5C5-7384206E70FE",
"type": "BoxGeometry",
@@ -43,14 +51,6 @@
"heightSegments": 1,
"openEnded": false
},
- {
- "uuid": "51BB3E54-D2DF-4576-9953-FB8E940588B5",
- "type": "PlaneGeometry",
- "width": 1000,
- "height": 1000,
- "widthSegments": 1,
- "heightSegments": 1
- },
{
"uuid": "4DECFAB5-6FD1-4D84-9A29-565807B074EA",
"type": "IcosahedronGeometry",
@@ -59,25 +59,25 @@
}],
"materials": [
{
- "uuid": "B5943856-E404-45D9-A427-4774202C2CD0",
+ "uuid": "4AE8130E-B6A8-47BC-ACCF-060973C74044",
"type": "MeshPhongMaterial",
- "color": 37119,
+ "color": 16777215,
"emissive": 0,
"specular": 1118481,
"shininess": 30
},
{
- "uuid": "3F872310-2067-4BE4-9250-5B3F4E43797E",
+ "uuid": "B5943856-E404-45D9-A427-4774202C2CD0",
"type": "MeshPhongMaterial",
- "color": 15859456,
+ "color": 37119,
"emissive": 0,
"specular": 1118481,
"shininess": 30
},
{
- "uuid": "4AE8130E-B6A8-47BC-ACCF-060973C74044",
+ "uuid": "3F872310-2067-4BE4-9250-5B3F4E43797E",
"type": "MeshPhongMaterial",
- "color": 16777215,
+ "color": 15859456,
"emissive": 0,
"specular": 1118481,
"shininess": 30
@@ -97,19 +97,34 @@
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
"children": [
{
- "uuid": "60B69C58-4201-43FD-815E-AD2EDFBBD0CE",
- "type": "PerspectiveCamera",
- "name": "PerspectiveCamera 1",
- "fov": 50,
- "aspect": 1,
- "near": 100,
- "far": 10000,
- "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,100,400,1]
+ "uuid": "B7CBBC6F-EC26-49B5-8D0D-67D9C535924B",
+ "type": "Group",
+ "name": "Dummy",
+ "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,100,400,1],
+ "children": [
+ {
+ "uuid": "60B69C58-4201-43FD-815E-AD2EDFBBD0CE",
+ "type": "PerspectiveCamera",
+ "name": "PerspectiveCamera",
+ "fov": 50,
+ "aspect": 1,
+ "near": 100,
+ "far": 10000,
+ "matrix": [-1,0,-1.2246468525851679e-16,0,0,1,0,0,1.2246468525851679e-16,0,-1,0,0,0,0,1]
+ }]
+ },
+ {
+ "uuid": "A460C230-DC88-4A8F-A3FB-AA0FE735F3ED",
+ "type": "Mesh",
+ "name": "Plane",
+ "geometry": "51BB3E54-D2DF-4576-9953-FB8E940588B5",
+ "material": "4AE8130E-B6A8-47BC-ACCF-060973C74044",
+ "matrix": [1,0,0,0,0,0.040785226970911026,-0.9991679191589355,0,0,0.9991679191589355,0.040785226970911026,0,0,-50,0,1]
},
{
"uuid": "26DAAD69-725D-43B7-AF9D-990A99DEF8C5",
"type": "Mesh",
- "name": "Box 1",
+ "name": "Box",
"geometry": "D8E200D3-27BC-49F8-A5C5-7384206E70FE",
"material": "B5943856-E404-45D9-A427-4774202C2CD0",
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
@@ -117,27 +132,18 @@
{
"uuid": "AAAFF2D6-4725-4AFC-A9FE-26419B11011F",
"type": "Mesh",
- "name": "Cylinder 3",
+ "name": "Cylinder",
"geometry": "25BA32DB-8B02-4ABA-A77C-69868C464A1A",
"material": "3F872310-2067-4BE4-9250-5B3F4E43797E",
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-130,-15,0,1]
},
{
- "uuid": "A460C230-DC88-4A8F-A3FB-AA0FE735F3ED",
+ "uuid": "B855E267-A266-4098-ACD6-6A1FDE7B88BA",
"type": "Mesh",
- "name": "Plane 4",
- "geometry": "51BB3E54-D2DF-4576-9953-FB8E940588B5",
- "material": "4AE8130E-B6A8-47BC-ACCF-060973C74044",
- "matrix": [1,0,0,0,0,0.040785059332847595,-0.9991679191589355,0,0,0.9991679191589355,0.040785059332847595,0,0,-50,0,1]
- },
- {
- "uuid": "3412781E-27CC-43C3-A5DB-54C0C8E42ED6",
- "type": "PointLight",
- "name": "PointLight 2",
- "color": 12773063,
- "intensity": 1,
- "distance": 0,
- "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,88.12999725341797,8.3100004196167,125.44999694824219,1]
+ "name": "Icosahedron",
+ "geometry": "4DECFAB5-6FD1-4D84-9A29-565807B074EA",
+ "material": "E1826901-7922-4584-A25D-6D487E2C9BBD",
+ "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,130,-10,0,1]
},
{
"uuid": "E2939A7B-5E40-438A-8C1B-32126FBC6892",
@@ -146,23 +152,31 @@
"color": 9474221,
"intensity": 0.75,
"distance": 0,
+ "decay": 1,
"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-93.86000061035156,127.12999725341797,-114.30000305175781,1]
},
{
- "uuid": "B855E267-A266-4098-ACD6-6A1FDE7B88BA",
- "type": "Mesh",
- "name": "Icosahedron 1",
- "geometry": "4DECFAB5-6FD1-4D84-9A29-565807B074EA",
- "material": "E1826901-7922-4584-A25D-6D487E2C9BBD",
- "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,130,-10,0,1]
+ "uuid": "3412781E-27CC-43C3-A5DB-54C0C8E42ED6",
+ "type": "PointLight",
+ "name": "PointLight 2",
+ "color": 12773063,
+ "intensity": 1,
+ "distance": 0,
+ "decay": 1,
+ "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,88.12999725341797,8.3100004196167,125.44999694824219,1]
}]
}
},
"scripts": {
"60B69C58-4201-43FD-815E-AD2EDFBBD0CE": [
{
- "name": "Camera Orbit",
- "source": "player.setCamera( this );\n\nfunction update( event ) {\n\n\tvar time = event.time * 0.001;\n\n\tthis.position.x = Math.sin( time ) * 400;\n\tthis.position.z = Math.cos( time ) * 400;\n\tthis.lookAt( scene.position );\n\n}"
+ "name": "Player Camera",
+ "source": "player.setCamera( this );"
+ }],
+ "B7CBBC6F-EC26-49B5-8D0D-67D9C535924B": [
+ {
+ "name": "Orbit",
+ "source": "function update( event ) {\n\n\tvar time = event.time * 0.001;\n\n\tthis.position.x = Math.sin( time ) * 400;\n\tthis.position.z = Math.cos( time ) * 400;\n\tthis.lookAt( scene.position );\n\n}"
}]
}
-}
+}
\ No newline at end of file
diff --git a/editor/examples/pong.app.json b/editor/examples/pong.app.json
index fd04fc724049eb..9b8a983c54e653 100755
--- a/editor/examples/pong.app.json
+++ b/editor/examples/pong.app.json
@@ -128,7 +128,7 @@
"31517222-A9A7-4EAF-B5F6-60751C0BABA3": [
{
"name": "Game logic",
- "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar position = ball.position;\n\nvar velocity = new THREE.Vector3();\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = Math.random() - 0.5;\ndirection.normalize();\n\nvar pad1 = this.getObjectByName( 'Pad 1' );\nvar pad2 = this.getObjectByName( 'Pad 2' );\n\nvar raycaster = new THREE.Raycaster();\nvar objects = [ pad1, pad2 ];\n\n//\n\nfunction mousemove( event ) {\n\n\tpad1.position.z = ( event.clientX / player.width ) * 300 - 150;\n\tpad2.position.z = - pad1.position.z;\n\n}\n\nfunction update( event ) {\n\n\tif ( position.x < -300 || position.x > 300 ) {\n\t\t\n\t\tdirection.x = - direction.x;\n\t\t\n\t}\n\n\tif ( position.z < -200 || position.z > 200 ) {\n\t\t\n\t\tdirection.z = - direction.z;\n\t\t\n\t}\n\t\n\traycaster.set( position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( objects );\n\t\n\tif ( intersections.length > 0 ) {\n\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 10 ) {\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n\tposition.add( velocity.copy( direction ).multiplyScalar( event.delta / 2 ) );\n\n}"
+ "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar position = ball.position;\n\nvar velocity = new THREE.Vector3();\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = Math.random() - 0.5;\ndirection.normalize();\n\nvar pad1 = this.getObjectByName( 'Pad 1' );\nvar pad2 = this.getObjectByName( 'Pad 2' );\n\nvar raycaster = new THREE.Raycaster();\nvar objects = [ pad1, pad2 ];\n\n//\n\nfunction mousemove( event ) {\n\n\tpad1.position.z = ( event.clientX / player.width ) * 300 - 150;\n\tpad2.position.z = - pad1.position.z;\n\n}\n\nfunction update( event ) {\n\t\n\tif ( position.x < -300 || position.x > 300 ) direction.x = - direction.x;\n\tif ( position.z < -200 || position.z > 200 ) direction.z = - direction.z;\n\t\n\tposition.x = Math.max( - 300, Math.min( 300, position.x ) );\n\tposition.z = Math.max( - 200, Math.min( 200, position.z ) );\n\t\n\traycaster.set( position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( objects );\n\t\n\tif ( intersections.length > 0 ) {\n\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 10 ) {\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n\tposition.add( velocity.copy( direction ).multiplyScalar( event.delta / 2 ) );\n\n}"
}]
}
}
\ No newline at end of file
diff --git a/editor/index.html b/editor/index.html
index 51544dfce46c3c..4ac1c041e8cd8b 100644
--- a/editor/index.html
+++ b/editor/index.html
@@ -41,6 +41,7 @@
+
diff --git a/editor/js/Editor.js b/editor/js/Editor.js
index d5a45fa20601e9..34412e6561f3ad 100644
--- a/editor/js/Editor.js
+++ b/editor/js/Editor.js
@@ -470,6 +470,9 @@ Editor.prototype = {
return {
+ project: {
+ vr: this.config.getKey( 'project/vr' )
+ },
camera: this.camera.toJSON(),
scene: this.scene.toJSON(),
scripts: this.scripts
diff --git a/editor/js/Menubar.Edit.js b/editor/js/Menubar.Edit.js
index 246713c83d0a6c..dbe75877094dcb 100644
--- a/editor/js/Menubar.Edit.js
+++ b/editor/js/Menubar.Edit.js
@@ -53,38 +53,6 @@ Menubar.Edit = function ( editor ) {
} );
options.add( option );
- //
-
- options.add( new UI.HorizontalRule() );
-
- // Flatten
-
- var option = new UI.Panel();
- option.setClass( 'option' );
- option.setTextContent( 'Flatten' );
- option.onClick( function () {
-
- var object = editor.selected;
-
- if ( object.parent === undefined ) return; // avoid flattening the camera or scene
-
- if ( confirm( 'Flatten ' + object.name + '?' ) === false ) return;
-
- var geometry = object.geometry;
-
- geometry.applyMatrix( object.matrix );
- geometry.verticesNeedUpdate = true;
- geometry.normalsNeedUpdate = true;
-
- object.position.set( 0, 0, 0 );
- object.rotation.set( 0, 0, 0 );
- object.scale.set( 1, 1, 1 );
-
- editor.signals.objectChanged.dispatch( object );
-
- } );
- options.add( option );
-
return container;
};
diff --git a/editor/js/Player.js b/editor/js/Player.js
index 72194b8a00242e..3b8fe27fe35c85 100644
--- a/editor/js/Player.js
+++ b/editor/js/Player.js
@@ -19,7 +19,7 @@ var Player = function ( editor ) {
if ( player.dom === undefined ) return;
- player.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
+ player.setSize( container.dom.clientWidth, container.dom.clientHeight );
} );
@@ -27,9 +27,8 @@ var Player = function ( editor ) {
container.setDisplay( '' );
- player.setVR( editor.config.getKey( 'project/vr' ) );
player.load( editor.toJSON() );
- player.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
+ player.setSize( container.dom.clientWidth, container.dom.clientHeight );
player.play();
container.dom.appendChild( player.dom );
diff --git a/editor/js/Script.js b/editor/js/Script.js
index 80fa696be5449b..abcb6d24924543 100644
--- a/editor/js/Script.js
+++ b/editor/js/Script.js
@@ -15,7 +15,7 @@ var Script = function ( editor ) {
var header = new UI.Panel();
header.setPadding( '10px' );
container.add( header );
-
+
var title = new UI.Text().setColor( '#fff' );
header.add( title );
@@ -59,16 +59,101 @@ var Script = function ( editor ) {
clearTimeout( delay );
delay = setTimeout( function () {
- currentScript.source = codemirror.getValue();
+ var value = codemirror.getValue();
+
+ if ( validate( value ) ) {
+
+ currentScript.source = value;
+ signals.scriptChanged.dispatch( currentScript );
- signals.scriptChanged.dispatch( currentScript );
+ }
}, 300 );
});
+ // validate
+
+ var errorLines = [];
+ var widgets = [];
+
+ var validate = function ( string ) {
+
+ var syntax, errors;
+
+ return codemirror.operation( function () {
+
+ while ( errorLines.length > 0 ) {
+
+ codemirror.removeLineClass( errorLines.shift(), 'background', 'errorLine' );
+
+ }
+
+ for ( var i = 0; i < widgets.length; i ++ ) {
+
+ codemirror.removeLineWidget( widgets[ i ] );
+
+ }
+
+ widgets.length = 0;
+
+ //
+
+ try {
+
+ syntax = esprima.parse( string, { tolerant: true } );
+ errors = syntax.errors;
+
+ for ( var i = 0; i < errors.length; i ++ ) {
+
+ var error = errors[ i ];
+
+ var message = document.createElement( 'div' );
+ message.className = 'esprima-error';
+ message.textContent = error.message.replace(/Line [0-9]+: /, '');
+
+ var lineNumber = error.lineNumber - 1;
+ errorLines.push( lineNumber );
+
+ codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
+
+ var widget = codemirror.addLineWidget(
+ lineNumber,
+ message
+ );
+
+ widgets.push( widget );
+
+ }
+
+ } catch ( error ) {
+
+ var message = document.createElement( 'div' );
+ message.className = 'esprima-error';
+ message.textContent = error.message.replace(/Line [0-9]+: /, '');
+
+ var lineNumber = error.lineNumber - 1;
+ errorLines.push( lineNumber );
+
+ codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
+
+ var widget = codemirror.addLineWidget(
+ lineNumber,
+ message
+ );
+
+ widgets.push( widget );
+
+ }
+
+ return errorLines.length === 0;
+
+ });
+
+ };
+
//
-
+
signals.editorCleared.add( function () {
container.setDisplay( 'none' );
diff --git a/editor/js/Sidebar.Geometry.js b/editor/js/Sidebar.Geometry.js
index 1fd62143bef2ad..bc3efd9e40e1be 100644
--- a/editor/js/Sidebar.Geometry.js
+++ b/editor/js/Sidebar.Geometry.js
@@ -17,6 +17,56 @@ Sidebar.Geometry = function ( editor ) {
var geometryType = new UI.Text().setTextTransform( 'uppercase' );
container.addStatic( geometryType );
+
+ // Actions
+
+ var objectActions = new UI.Select().setPosition('absolute').setRight( '8px' ).setFontSize( '11px' );
+ objectActions.setOptions( {
+
+ 'Actions': 'Actions',
+ 'Flatten': 'Flatten'
+
+ } );
+ objectActions.onClick( function ( event ) {
+
+ event.stopPropagation(); // Avoid panel collapsing
+
+ } );
+ objectActions.onChange( function ( event ) {
+
+ var object = editor.selected;
+
+ switch ( this.getValue() ) {
+
+ case 'Flatten':
+
+ var object = editor.selected;
+
+ if ( confirm( 'Flatten ' + object.name + '?' ) === false ) return;
+
+ var geometry = object.geometry;
+
+ geometry.applyMatrix( object.matrix );
+ geometry.verticesNeedUpdate = true;
+ geometry.normalsNeedUpdate = true;
+
+ object.position.set( 0, 0, 0 );
+ object.rotation.set( 0, 0, 0 );
+ object.scale.set( 1, 1, 1 );
+
+ editor.signals.objectChanged.dispatch( object );
+
+ break;
+
+ }
+
+ this.setValue( 'Actions' );
+
+ signals.objectChanged.dispatch( object );
+
+ } );
+ container.addStatic( objectActions );
+
container.add( new UI.Break() );
// uuid
diff --git a/editor/js/Sidebar.Object3D.js b/editor/js/Sidebar.Object3D.js
index 4bea46dc1ed46b..0aae11c0e456f6 100644
--- a/editor/js/Sidebar.Object3D.js
+++ b/editor/js/Sidebar.Object3D.js
@@ -18,6 +18,8 @@ Sidebar.Object3D = function ( editor ) {
var objectType = new UI.Text().setTextTransform( 'uppercase' );
container.addStatic( objectType );
+ // Actions
+
var objectActions = new UI.Select().setPosition('absolute').setRight( '8px' ).setFontSize( '11px' );
objectActions.setOptions( {
diff --git a/editor/js/libs/app.js b/editor/js/libs/app.js
index 5e1bbdd389fa8b..04ec67ca354e3d 100644
--- a/editor/js/libs/app.js
+++ b/editor/js/libs/app.js
@@ -22,12 +22,15 @@ var APP = {
this.load = function ( json ) {
+ vr = json.project.vr;
+
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( 0x000000 );
renderer.setPixelRatio( window.devicePixelRatio );
+ this.dom = renderer.domElement;
- camera = loader.parse( json.camera );
- scene = loader.parse( json.scene );
+ this.setScene( loader.parse( json.scene ) );
+ this.setCamera( loader.parse( json.camera ) );
events = {
keydown: [],
@@ -72,42 +75,62 @@ var APP = {
}
- this.dom = renderer.domElement;
+ };
+
+ this.setCamera = function ( value ) {
+
+ camera = value;
+ camera.aspect = this.width / this.height;
+ camera.updateProjectionMatrix();
+
if ( vr === true ) {
+ if ( camera.parent === undefined ) {
+
+ // camera needs to be in the scene so camera2 matrix updates
+
+ scene.add( camera );
+
+ }
+
+ var camera2 = camera.clone();
+ camera.add( camera2 );
+
+ camera = camera2;
+
controls = new THREE.VRControls( camera );
renderer = new THREE.VREffect( renderer );
- this.dom.addEventListener( 'dblclick', function () {
+ document.addEventListener( 'keyup', function ( event ) {
- renderer.setFullScreen( true );
+ switch ( event.keyCode ) {
+ case 90:
+ controls.zeroSensor();
+ break;
+ }
} );
- }
- };
+ this.dom.addEventListener( 'dblclick', function () {
- this.setCamera = function ( value ) {
+ renderer.setFullScreen( true );
- camera = value;
- camera.aspect = this.width / this.height;
- camera.updateProjectionMatrix();
+ } );
+
+ }
};
- this.setVR = function ( value ) {
+ this.setScene = function ( value ) {
- vr = value;
+ scene = value;
- };
+ },
this.setSize = function ( width, height ) {
- if ( vr ) {
- width = 1280;
- height = 800;
- }
+ if ( renderer._fullScreen ) return;
this.width = width;
this.height = height;
diff --git a/editor/js/libs/esprima.js b/editor/js/libs/esprima.js
new file mode 100644
index 00000000000000..a1f80c83e13445
--- /dev/null
+++ b/editor/js/libs/esprima.js
@@ -0,0 +1,4156 @@
+/*
+ Copyright (C) 2013 Ariya Hidayat expect(value)
+ * @since 2.0
+ */
+ function expectCommaSeparator() {
+ var token;
+
+ if (extra.errors) {
+ token = lookahead;
+ if (token.type === Token.Punctuator && token.value === ',') {
+ lex();
+ } else if (token.type === Token.Punctuator && token.value === ';') {
+ lex();
+ tolerateUnexpectedToken(token);
+ } else {
+ tolerateUnexpectedToken(token, Messages.UnexpectedToken);
+ }
+ } else {
+ expect(',');
+ }
+ }
+
+ // Expect the next token to match the specified keyword.
+ // If not, an exception will be thrown.
+
+ function expectKeyword(keyword) {
+ var token = lex();
+ if (token.type !== Token.Keyword || token.value !== keyword) {
+ throwUnexpectedToken(token);
+ }
+ }
+
+ // Return true if the next token matches the specified punctuator.
+
+ function match(value) {
+ return lookahead.type === Token.Punctuator && lookahead.value === value;
+ }
+
+ // Return true if the next token matches the specified keyword
+
+ function matchKeyword(keyword) {
+ return lookahead.type === Token.Keyword && lookahead.value === keyword;
+ }
+
+ // Return true if the next token is an assignment operator
+
+ function matchAssign() {
+ var op;
+
+ if (lookahead.type !== Token.Punctuator) {
+ return false;
+ }
+ op = lookahead.value;
+ return op === '=' ||
+ op === '*=' ||
+ op === '/=' ||
+ op === '%=' ||
+ op === '+=' ||
+ op === '-=' ||
+ op === '<<=' ||
+ op === '>>=' ||
+ op === '>>>=' ||
+ op === '&=' ||
+ op === '^=' ||
+ op === '|=';
+ }
+
+ function consumeSemicolon() {
+ var line, oldIndex = index, oldLineNumber = lineNumber,
+ oldLineStart = lineStart, oldLookahead = lookahead;
+
+ // Catch the very common case first: immediately a semicolon (U+003B).
+ if (source.charCodeAt(index) === 0x3B || match(';')) {
+ lex();
+ return;
+ }
+
+ line = lineNumber;
+ skipComment();
+ if (lineNumber !== line) {
+ index = oldIndex;
+ lineNumber = oldLineNumber;
+ lineStart = oldLineStart;
+ lookahead = oldLookahead;
+ return;
+ }
+
+ if (lookahead.type !== Token.EOF && !match('}')) {
+ throwUnexpectedToken(lookahead);
+ }
+ }
+
+ // Return true if provided expression is LeftHandSideExpression
+
+ function isLeftHandSide(expr) {
+ return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
+ }
+
+ // 11.1.4 Array Initialiser
+
+ function parseArrayInitialiser() {
+ var elements = [], node = new Node();
+
+ expect('[');
+
+ while (!match(']')) {
+ if (match(',')) {
+ lex();
+ elements.push(null);
+ } else {
+ elements.push(parseAssignmentExpression());
+
+ if (!match(']')) {
+ expect(',');
+ }
+ }
+ }
+
+ lex();
+
+ return node.finishArrayExpression(elements);
+ }
+
+ // 11.1.5 Object Initialiser
+
+ function parsePropertyFunction(param, first) {
+ var previousStrict, body, node = new Node();
+
+ previousStrict = strict;
+ body = parseFunctionSourceElements();
+ if (first && strict && isRestrictedWord(param[0].name)) {
+ tolerateUnexpectedToken(first, Messages.StrictParamName);
+ }
+ strict = previousStrict;
+ return node.finishFunctionExpression(null, param, [], body);
+ }
+
+ function parsePropertyMethodFunction() {
+ var previousStrict, param, method;
+
+ previousStrict = strict;
+ strict = true;
+ param = parseParams();
+ method = parsePropertyFunction(param.params);
+ strict = previousStrict;
+
+ return method;
+ }
+
+ function parseObjectPropertyKey() {
+ var token, node = new Node();
+
+ token = lex();
+
+ // Note: This function is called only from parseObjectProperty(), where
+ // EOF and Punctuator tokens are already filtered out.
+
+ if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
+ if (strict && token.octal) {
+ tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
+ }
+ return node.finishLiteral(token);
+ }
+
+ return node.finishIdentifier(token.value);
+ }
+
+ function parseObjectProperty() {
+ var token, key, id, value, param, node = new Node();
+
+ token = lookahead;
+
+ if (token.type === Token.Identifier) {
+
+ id = parseObjectPropertyKey();
+
+ // Property Assignment: Getter and Setter.
+
+ if (token.value === 'get' && !(match(':') || match('('))) {
+ key = parseObjectPropertyKey();
+ expect('(');
+ expect(')');
+ value = parsePropertyFunction([]);
+ return node.finishProperty('get', key, value, false, false);
+ }
+ if (token.value === 'set' && !(match(':') || match('('))) {
+ key = parseObjectPropertyKey();
+ expect('(');
+ token = lookahead;
+ if (token.type !== Token.Identifier) {
+ expect(')');
+ tolerateUnexpectedToken(token);
+ value = parsePropertyFunction([]);
+ } else {
+ param = [ parseVariableIdentifier() ];
+ expect(')');
+ value = parsePropertyFunction(param, token);
+ }
+ return node.finishProperty('set', key, value, false, false);
+ }
+ if (match(':')) {
+ lex();
+ value = parseAssignmentExpression();
+ return node.finishProperty('init', id, value, false, false);
+ }
+ if (match('(')) {
+ value = parsePropertyMethodFunction();
+ return node.finishProperty('init', id, value, true, false);
+ }
+
+ value = id;
+ return node.finishProperty('init', id, value, false, true);
+ }
+ if (token.type === Token.EOF || token.type === Token.Punctuator) {
+ throwUnexpectedToken(token);
+ } else {
+ key = parseObjectPropertyKey();
+ if (match(':')) {
+ lex();
+ value = parseAssignmentExpression();
+ return node.finishProperty('init', key, value, false, false);
+ }
+ if (match('(')) {
+ value = parsePropertyMethodFunction();
+ return node.finishProperty('init', key, value, true, false);
+ }
+ throwUnexpectedToken(lex());
+ }
+ }
+
+ function parseObjectInitialiser() {
+ var properties = [], property, name, key, kind, map = {}, toString = String, node = new Node();
+
+ expect('{');
+
+ while (!match('}')) {
+ property = parseObjectProperty();
+
+ if (property.key.type === Syntax.Identifier) {
+ name = property.key.name;
+ } else {
+ name = toString(property.key.value);
+ }
+ kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
+
+ key = '$' + name;
+ if (Object.prototype.hasOwnProperty.call(map, key)) {
+ if (map[key] === PropertyKind.Data) {
+ if (strict && kind === PropertyKind.Data) {
+ tolerateError(Messages.StrictDuplicateProperty);
+ } else if (kind !== PropertyKind.Data) {
+ tolerateError(Messages.AccessorDataProperty);
+ }
+ } else {
+ if (kind === PropertyKind.Data) {
+ tolerateError(Messages.AccessorDataProperty);
+ } else if (map[key] & kind) {
+ tolerateError(Messages.AccessorGetSet);
+ }
+ }
+ map[key] |= kind;
+ } else {
+ map[key] = kind;
+ }
+
+ properties.push(property);
+
+ if (!match('}')) {
+ expectCommaSeparator();
+ }
+ }
+
+ expect('}');
+
+ return node.finishObjectExpression(properties);
+ }
+
+ // 11.1.6 The Grouping Operator
+
+ function parseGroupExpression() {
+ var expr;
+
+ expect('(');
+
+ if (match(')')) {
+ lex();
+ return PlaceHolders.ArrowParameterPlaceHolder;
+ }
+
+ ++state.parenthesisCount;
+
+ expr = parseExpression();
+
+ expect(')');
+
+ return expr;
+ }
+
+
+ // 11.1 Primary Expressions
+
+ function parsePrimaryExpression() {
+ var type, token, expr, node;
+
+ if (match('(')) {
+ return parseGroupExpression();
+ }
+
+ if (match('[')) {
+ return parseArrayInitialiser();
+ }
+
+ if (match('{')) {
+ return parseObjectInitialiser();
+ }
+
+ type = lookahead.type;
+ node = new Node();
+
+ if (type === Token.Identifier) {
+ expr = node.finishIdentifier(lex().value);
+ } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
+ if (strict && lookahead.octal) {
+ tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
+ }
+ expr = node.finishLiteral(lex());
+ } else if (type === Token.Keyword) {
+ if (matchKeyword('function')) {
+ return parseFunctionExpression();
+ }
+ if (matchKeyword('this')) {
+ lex();
+ expr = node.finishThisExpression();
+ } else {
+ throwUnexpectedToken(lex());
+ }
+ } else if (type === Token.BooleanLiteral) {
+ token = lex();
+ token.value = (token.value === 'true');
+ expr = node.finishLiteral(token);
+ } else if (type === Token.NullLiteral) {
+ token = lex();
+ token.value = null;
+ expr = node.finishLiteral(token);
+ } else if (match('/') || match('/=')) {
+ if (typeof extra.tokens !== 'undefined') {
+ expr = node.finishLiteral(collectRegex());
+ } else {
+ expr = node.finishLiteral(scanRegExp());
+ }
+ peek();
+ } else {
+ throwUnexpectedToken(lex());
+ }
+
+ return expr;
+ }
+
+ // 11.2 Left-Hand-Side Expressions
+
+ function parseArguments() {
+ var args = [];
+
+ expect('(');
+
+ if (!match(')')) {
+ while (index < length) {
+ args.push(parseAssignmentExpression());
+ if (match(')')) {
+ break;
+ }
+ expectCommaSeparator();
+ }
+ }
+
+ expect(')');
+
+ return args;
+ }
+
+ function parseNonComputedProperty() {
+ var token, node = new Node();
+
+ token = lex();
+
+ if (!isIdentifierName(token)) {
+ throwUnexpectedToken(token);
+ }
+
+ return node.finishIdentifier(token.value);
+ }
+
+ function parseNonComputedMember() {
+ expect('.');
+
+ return parseNonComputedProperty();
+ }
+
+ function parseComputedMember() {
+ var expr;
+
+ expect('[');
+
+ expr = parseExpression();
+
+ expect(']');
+
+ return expr;
+ }
+
+ function parseNewExpression() {
+ var callee, args, node = new Node();
+
+ expectKeyword('new');
+ callee = parseLeftHandSideExpression();
+ args = match('(') ? parseArguments() : [];
+
+ return node.finishNewExpression(callee, args);
+ }
+
+ function parseLeftHandSideExpressionAllowCall() {
+ var expr, args, property, startToken, previousAllowIn = state.allowIn;
+
+ startToken = lookahead;
+ state.allowIn = true;
+ expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+ for (;;) {
+ if (match('.')) {
+ property = parseNonComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+ } else if (match('(')) {
+ args = parseArguments();
+ expr = new WrappingNode(startToken).finishCallExpression(expr, args);
+ } else if (match('[')) {
+ property = parseComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
+ } else {
+ break;
+ }
+ }
+ state.allowIn = previousAllowIn;
+
+ return expr;
+ }
+
+ function parseLeftHandSideExpression() {
+ var expr, property, startToken;
+ assert(state.allowIn, 'callee of new expression always allow in keyword.');
+
+ startToken = lookahead;
+
+ expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
+
+ for (;;) {
+ if (match('[')) {
+ property = parseComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
+ } else if (match('.')) {
+ property = parseNonComputedMember();
+ expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+ } else {
+ break;
+ }
+ }
+ return expr;
+ }
+
+ // 11.3 Postfix Expressions
+
+ function parsePostfixExpression() {
+ var expr, token, startToken = lookahead;
+
+ expr = parseLeftHandSideExpressionAllowCall();
+
+ if (lookahead.type === Token.Punctuator) {
+ if ((match('++') || match('--')) && !peekLineTerminator()) {
+ // 11.3.1, 11.3.2
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+ tolerateError(Messages.StrictLHSPostfix);
+ }
+
+ if (!isLeftHandSide(expr)) {
+ tolerateError(Messages.InvalidLHSInAssignment);
+ }
+
+ token = lex();
+ expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
+ }
+ }
+
+ return expr;
+ }
+
+ // 11.4 Unary Operators
+
+ function parseUnaryExpression() {
+ var token, expr, startToken;
+
+ if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
+ expr = parsePostfixExpression();
+ } else if (match('++') || match('--')) {
+ startToken = lookahead;
+ token = lex();
+ expr = parseUnaryExpression();
+ // 11.4.4, 11.4.5
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+ tolerateError(Messages.StrictLHSPrefix);
+ }
+
+ if (!isLeftHandSide(expr)) {
+ tolerateError(Messages.InvalidLHSInAssignment);
+ }
+
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+ } else if (match('+') || match('-') || match('~') || match('!')) {
+ startToken = lookahead;
+ token = lex();
+ expr = parseUnaryExpression();
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+ } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
+ startToken = lookahead;
+ token = lex();
+ expr = parseUnaryExpression();
+ expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+ if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
+ tolerateError(Messages.StrictDelete);
+ }
+ } else {
+ expr = parsePostfixExpression();
+ }
+
+ return expr;
+ }
+
+ function binaryPrecedence(token, allowIn) {
+ var prec = 0;
+
+ if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
+ return 0;
+ }
+
+ switch (token.value) {
+ case '||':
+ prec = 1;
+ break;
+
+ case '&&':
+ prec = 2;
+ break;
+
+ case '|':
+ prec = 3;
+ break;
+
+ case '^':
+ prec = 4;
+ break;
+
+ case '&':
+ prec = 5;
+ break;
+
+ case '==':
+ case '!=':
+ case '===':
+ case '!==':
+ prec = 6;
+ break;
+
+ case '<':
+ case '>':
+ case '<=':
+ case '>=':
+ case 'instanceof':
+ prec = 7;
+ break;
+
+ case 'in':
+ prec = allowIn ? 7 : 0;
+ break;
+
+ case '<<':
+ case '>>':
+ case '>>>':
+ prec = 8;
+ break;
+
+ case '+':
+ case '-':
+ prec = 9;
+ break;
+
+ case '*':
+ case '/':
+ case '%':
+ prec = 11;
+ break;
+
+ default:
+ break;
+ }
+
+ return prec;
+ }
+
+ // 11.5 Multiplicative Operators
+ // 11.6 Additive Operators
+ // 11.7 Bitwise Shift Operators
+ // 11.8 Relational Operators
+ // 11.9 Equality Operators
+ // 11.10 Binary Bitwise Operators
+ // 11.11 Binary Logical Operators
+
+ function parseBinaryExpression() {
+ var marker, markers, expr, token, prec, stack, right, operator, left, i;
+
+ marker = lookahead;
+ left = parseUnaryExpression();
+ if (left === PlaceHolders.ArrowParameterPlaceHolder) {
+ return left;
+ }
+
+ token = lookahead;
+ prec = binaryPrecedence(token, state.allowIn);
+ if (prec === 0) {
+ return left;
+ }
+ token.prec = prec;
+ lex();
+
+ markers = [marker, lookahead];
+ right = parseUnaryExpression();
+
+ stack = [left, token, right];
+
+ while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
+
+ // Reduce: make a binary expression from the three topmost entries.
+ while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
+ right = stack.pop();
+ operator = stack.pop().value;
+ left = stack.pop();
+ markers.pop();
+ expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
+ stack.push(expr);
+ }
+
+ // Shift.
+ token = lex();
+ token.prec = prec;
+ stack.push(token);
+ markers.push(lookahead);
+ expr = parseUnaryExpression();
+ stack.push(expr);
+ }
+
+ // Final reduce to clean-up the stack.
+ i = stack.length - 1;
+ expr = stack[i];
+ markers.pop();
+ while (i > 1) {
+ expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
+ i -= 2;
+ }
+
+ return expr;
+ }
+
+
+ // 11.12 Conditional Operator
+
+ function parseConditionalExpression() {
+ var expr, previousAllowIn, consequent, alternate, startToken;
+
+ startToken = lookahead;
+
+ expr = parseBinaryExpression();
+ if (expr === PlaceHolders.ArrowParameterPlaceHolder) {
+ return expr;
+ }
+ if (match('?')) {
+ lex();
+ previousAllowIn = state.allowIn;
+ state.allowIn = true;
+ consequent = parseAssignmentExpression();
+ state.allowIn = previousAllowIn;
+ expect(':');
+ alternate = parseAssignmentExpression();
+
+ expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
+ }
+
+ return expr;
+ }
+
+ // [ES6] 14.2 Arrow Function
+
+ function parseConciseBody() {
+ if (match('{')) {
+ return parseFunctionSourceElements();
+ }
+ return parseAssignmentExpression();
+ }
+
+ function reinterpretAsCoverFormalsList(expressions) {
+ var i, len, param, params, defaults, defaultCount, options, rest, token;
+
+ params = [];
+ defaults = [];
+ defaultCount = 0;
+ rest = null;
+ options = {
+ paramSet: {}
+ };
+
+ for (i = 0, len = expressions.length; i < len; i += 1) {
+ param = expressions[i];
+ if (param.type === Syntax.Identifier) {
+ params.push(param);
+ defaults.push(null);
+ validateParam(options, param, param.name);
+ } else if (param.type === Syntax.AssignmentExpression) {
+ params.push(param.left);
+ defaults.push(param.right);
+ ++defaultCount;
+ validateParam(options, param.left, param.left.name);
+ } else {
+ return null;
+ }
+ }
+
+ if (options.message === Messages.StrictParamDupe) {
+ token = strict ? options.stricted : options.firstRestricted;
+ throwUnexpectedToken(token, options.message);
+ }
+
+ if (defaultCount === 0) {
+ defaults = [];
+ }
+
+ return {
+ params: params,
+ defaults: defaults,
+ rest: rest,
+ stricted: options.stricted,
+ firstRestricted: options.firstRestricted,
+ message: options.message
+ };
+ }
+
+ function parseArrowFunctionExpression(options, node) {
+ var previousStrict, body;
+
+ expect('=>');
+ previousStrict = strict;
+
+ body = parseConciseBody();
+
+ if (strict && options.firstRestricted) {
+ throwUnexpectedToken(options.firstRestricted, options.message);
+ }
+ if (strict && options.stricted) {
+ tolerateUnexpectedToken(options.stricted, options.message);
+ }
+
+ strict = previousStrict;
+
+ return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
+ }
+
+ // 11.13 Assignment Operators
+
+ function parseAssignmentExpression() {
+ var oldParenthesisCount, token, expr, right, list, startToken;
+
+ oldParenthesisCount = state.parenthesisCount;
+
+ startToken = lookahead;
+ token = lookahead;
+
+ expr = parseConditionalExpression();
+
+ if (expr === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) {
+ if (state.parenthesisCount === oldParenthesisCount ||
+ state.parenthesisCount === (oldParenthesisCount + 1)) {
+ if (expr.type === Syntax.Identifier) {
+ list = reinterpretAsCoverFormalsList([ expr ]);
+ } else if (expr.type === Syntax.AssignmentExpression) {
+ list = reinterpretAsCoverFormalsList([ expr ]);
+ } else if (expr.type === Syntax.SequenceExpression) {
+ list = reinterpretAsCoverFormalsList(expr.expressions);
+ } else if (expr === PlaceHolders.ArrowParameterPlaceHolder) {
+ list = reinterpretAsCoverFormalsList([]);
+ }
+ if (list) {
+ return parseArrowFunctionExpression(list, new WrappingNode(startToken));
+ }
+ }
+ }
+
+ if (matchAssign()) {
+ // LeftHandSideExpression
+ if (!isLeftHandSide(expr)) {
+ tolerateError(Messages.InvalidLHSInAssignment);
+ }
+
+ // 11.13.1
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
+ tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
+ }
+
+ token = lex();
+ right = parseAssignmentExpression();
+ expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
+ }
+
+ return expr;
+ }
+
+ // 11.14 Comma Operator
+
+ function parseExpression() {
+ var expr, startToken = lookahead, expressions;
+
+ expr = parseAssignmentExpression();
+
+ if (match(',')) {
+ expressions = [expr];
+
+ while (index < length) {
+ if (!match(',')) {
+ break;
+ }
+ lex();
+ expressions.push(parseAssignmentExpression());
+ }
+
+ expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
+ }
+
+ return expr;
+ }
+
+ // 12.1 Block
+
+ function parseStatementList() {
+ var list = [],
+ statement;
+
+ while (index < length) {
+ if (match('}')) {
+ break;
+ }
+ statement = parseSourceElement();
+ if (typeof statement === 'undefined') {
+ break;
+ }
+ list.push(statement);
+ }
+
+ return list;
+ }
+
+ function parseBlock() {
+ var block, node = new Node();
+
+ expect('{');
+
+ block = parseStatementList();
+
+ expect('}');
+
+ return node.finishBlockStatement(block);
+ }
+
+ // 12.2 Variable Statement
+
+ function parseVariableIdentifier() {
+ var token, node = new Node();
+
+ token = lex();
+
+ if (token.type !== Token.Identifier) {
+ if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
+ tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+ } else {
+ throwUnexpectedToken(token);
+ }
+ }
+
+ return node.finishIdentifier(token.value);
+ }
+
+ function parseVariableDeclaration(kind) {
+ var init = null, id, node = new Node();
+
+ id = parseVariableIdentifier();
+
+ // 12.2.1
+ if (strict && isRestrictedWord(id.name)) {
+ tolerateError(Messages.StrictVarName);
+ }
+
+ if (kind === 'const') {
+ expect('=');
+ init = parseAssignmentExpression();
+ } else if (match('=')) {
+ lex();
+ init = parseAssignmentExpression();
+ }
+
+ return node.finishVariableDeclarator(id, init);
+ }
+
+ function parseVariableDeclarationList(kind) {
+ var list = [];
+
+ do {
+ list.push(parseVariableDeclaration(kind));
+ if (!match(',')) {
+ break;
+ }
+ lex();
+ } while (index < length);
+
+ return list;
+ }
+
+ function parseVariableStatement(node) {
+ var declarations;
+
+ expectKeyword('var');
+
+ declarations = parseVariableDeclarationList();
+
+ consumeSemicolon();
+
+ return node.finishVariableDeclaration(declarations, 'var');
+ }
+
+ // kind may be `const` or `let`
+ // Both are experimental and not in the specification yet.
+ // see http://wiki.ecmascript.org/doku.php?id=harmony:const
+ // and http://wiki.ecmascript.org/doku.php?id=harmony:let
+ function parseConstLetDeclaration(kind) {
+ var declarations, node = new Node();
+
+ expectKeyword(kind);
+
+ declarations = parseVariableDeclarationList(kind);
+
+ consumeSemicolon();
+
+ return node.finishVariableDeclaration(declarations, kind);
+ }
+
+ // 12.3 Empty Statement
+
+ function parseEmptyStatement() {
+ var node = new Node();
+ expect(';');
+ return node.finishEmptyStatement();
+ }
+
+ // 12.4 Expression Statement
+
+ function parseExpressionStatement(node) {
+ var expr = parseExpression();
+ consumeSemicolon();
+ return node.finishExpressionStatement(expr);
+ }
+
+ // 12.5 If statement
+
+ function parseIfStatement(node) {
+ var test, consequent, alternate;
+
+ expectKeyword('if');
+
+ expect('(');
+
+ test = parseExpression();
+
+ expect(')');
+
+ consequent = parseStatement();
+
+ if (matchKeyword('else')) {
+ lex();
+ alternate = parseStatement();
+ } else {
+ alternate = null;
+ }
+
+ return node.finishIfStatement(test, consequent, alternate);
+ }
+
+ // 12.6 Iteration Statements
+
+ function parseDoWhileStatement(node) {
+ var body, test, oldInIteration;
+
+ expectKeyword('do');
+
+ oldInIteration = state.inIteration;
+ state.inIteration = true;
+
+ body = parseStatement();
+
+ state.inIteration = oldInIteration;
+
+ expectKeyword('while');
+
+ expect('(');
+
+ test = parseExpression();
+
+ expect(')');
+
+ if (match(';')) {
+ lex();
+ }
+
+ return node.finishDoWhileStatement(body, test);
+ }
+
+ function parseWhileStatement(node) {
+ var test, body, oldInIteration;
+
+ expectKeyword('while');
+
+ expect('(');
+
+ test = parseExpression();
+
+ expect(')');
+
+ oldInIteration = state.inIteration;
+ state.inIteration = true;
+
+ body = parseStatement();
+
+ state.inIteration = oldInIteration;
+
+ return node.finishWhileStatement(test, body);
+ }
+
+ function parseForVariableDeclaration() {
+ var token, declarations, node = new Node();
+
+ token = lex();
+ declarations = parseVariableDeclarationList();
+
+ return node.finishVariableDeclaration(declarations, token.value);
+ }
+
+ function parseForStatement(node) {
+ var init, test, update, left, right, body, oldInIteration, previousAllowIn = state.allowIn;
+
+ init = test = update = null;
+
+ expectKeyword('for');
+
+ expect('(');
+
+ if (match(';')) {
+ lex();
+ } else {
+ if (matchKeyword('var') || matchKeyword('let')) {
+ state.allowIn = false;
+ init = parseForVariableDeclaration();
+ state.allowIn = previousAllowIn;
+
+ if (init.declarations.length === 1 && matchKeyword('in')) {
+ lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ }
+ } else {
+ state.allowIn = false;
+ init = parseExpression();
+ state.allowIn = previousAllowIn;
+
+ if (matchKeyword('in')) {
+ // LeftHandSideExpression
+ if (!isLeftHandSide(init)) {
+ tolerateError(Messages.InvalidLHSInForIn);
+ }
+
+ lex();
+ left = init;
+ right = parseExpression();
+ init = null;
+ }
+ }
+
+ if (typeof left === 'undefined') {
+ expect(';');
+ }
+ }
+
+ if (typeof left === 'undefined') {
+
+ if (!match(';')) {
+ test = parseExpression();
+ }
+ expect(';');
+
+ if (!match(')')) {
+ update = parseExpression();
+ }
+ }
+
+ expect(')');
+
+ oldInIteration = state.inIteration;
+ state.inIteration = true;
+
+ body = parseStatement();
+
+ state.inIteration = oldInIteration;
+
+ return (typeof left === 'undefined') ?
+ node.finishForStatement(init, test, update, body) :
+ node.finishForInStatement(left, right, body);
+ }
+
+ // 12.7 The continue statement
+
+ function parseContinueStatement(node) {
+ var label = null, key;
+
+ expectKeyword('continue');
+
+ // Optimize the most common form: 'continue;'.
+ if (source.charCodeAt(index) === 0x3B) {
+ lex();
+
+ if (!state.inIteration) {
+ throwError(Messages.IllegalContinue);
+ }
+
+ return node.finishContinueStatement(null);
+ }
+
+ if (peekLineTerminator()) {
+ if (!state.inIteration) {
+ throwError(Messages.IllegalContinue);
+ }
+
+ return node.finishContinueStatement(null);
+ }
+
+ if (lookahead.type === Token.Identifier) {
+ label = parseVariableIdentifier();
+
+ key = '$' + label.name;
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+ throwError(Messages.UnknownLabel, label.name);
+ }
+ }
+
+ consumeSemicolon();
+
+ if (label === null && !state.inIteration) {
+ throwError(Messages.IllegalContinue);
+ }
+
+ return node.finishContinueStatement(label);
+ }
+
+ // 12.8 The break statement
+
+ function parseBreakStatement(node) {
+ var label = null, key;
+
+ expectKeyword('break');
+
+ // Catch the very common case first: immediately a semicolon (U+003B).
+ if (source.charCodeAt(index) === 0x3B) {
+ lex();
+
+ if (!(state.inIteration || state.inSwitch)) {
+ throwError(Messages.IllegalBreak);
+ }
+
+ return node.finishBreakStatement(null);
+ }
+
+ if (peekLineTerminator()) {
+ if (!(state.inIteration || state.inSwitch)) {
+ throwError(Messages.IllegalBreak);
+ }
+
+ return node.finishBreakStatement(null);
+ }
+
+ if (lookahead.type === Token.Identifier) {
+ label = parseVariableIdentifier();
+
+ key = '$' + label.name;
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+ throwError(Messages.UnknownLabel, label.name);
+ }
+ }
+
+ consumeSemicolon();
+
+ if (label === null && !(state.inIteration || state.inSwitch)) {
+ throwError(Messages.IllegalBreak);
+ }
+
+ return node.finishBreakStatement(label);
+ }
+
+ // 12.9 The return statement
+
+ function parseReturnStatement(node) {
+ var argument = null;
+
+ expectKeyword('return');
+
+ if (!state.inFunctionBody) {
+ tolerateError(Messages.IllegalReturn);
+ }
+
+ // 'return' followed by a space and an identifier is very common.
+ if (source.charCodeAt(index) === 0x20) {
+ if (isIdentifierStart(source.charCodeAt(index + 1))) {
+ argument = parseExpression();
+ consumeSemicolon();
+ return node.finishReturnStatement(argument);
+ }
+ }
+
+ if (peekLineTerminator()) {
+ return node.finishReturnStatement(null);
+ }
+
+ if (!match(';')) {
+ if (!match('}') && lookahead.type !== Token.EOF) {
+ argument = parseExpression();
+ }
+ }
+
+ consumeSemicolon();
+
+ return node.finishReturnStatement(argument);
+ }
+
+ // 12.10 The with statement
+
+ function parseWithStatement(node) {
+ var object, body;
+
+ if (strict) {
+ // TODO(ikarienator): Should we update the test cases instead?
+ skipComment();
+ tolerateError(Messages.StrictModeWith);
+ }
+
+ expectKeyword('with');
+
+ expect('(');
+
+ object = parseExpression();
+
+ expect(')');
+
+ body = parseStatement();
+
+ return node.finishWithStatement(object, body);
+ }
+
+ // 12.10 The swith statement
+
+ function parseSwitchCase() {
+ var test, consequent = [], statement, node = new Node();
+
+ if (matchKeyword('default')) {
+ lex();
+ test = null;
+ } else {
+ expectKeyword('case');
+ test = parseExpression();
+ }
+ expect(':');
+
+ while (index < length) {
+ if (match('}') || matchKeyword('default') || matchKeyword('case')) {
+ break;
+ }
+ statement = parseStatement();
+ consequent.push(statement);
+ }
+
+ return node.finishSwitchCase(test, consequent);
+ }
+
+ function parseSwitchStatement(node) {
+ var discriminant, cases, clause, oldInSwitch, defaultFound;
+
+ expectKeyword('switch');
+
+ expect('(');
+
+ discriminant = parseExpression();
+
+ expect(')');
+
+ expect('{');
+
+ cases = [];
+
+ if (match('}')) {
+ lex();
+ return node.finishSwitchStatement(discriminant, cases);
+ }
+
+ oldInSwitch = state.inSwitch;
+ state.inSwitch = true;
+ defaultFound = false;
+
+ while (index < length) {
+ if (match('}')) {
+ break;
+ }
+ clause = parseSwitchCase();
+ if (clause.test === null) {
+ if (defaultFound) {
+ throwError(Messages.MultipleDefaultsInSwitch);
+ }
+ defaultFound = true;
+ }
+ cases.push(clause);
+ }
+
+ state.inSwitch = oldInSwitch;
+
+ expect('}');
+
+ return node.finishSwitchStatement(discriminant, cases);
+ }
+
+ // 12.13 The throw statement
+
+ function parseThrowStatement(node) {
+ var argument;
+
+ expectKeyword('throw');
+
+ if (peekLineTerminator()) {
+ throwError(Messages.NewlineAfterThrow);
+ }
+
+ argument = parseExpression();
+
+ consumeSemicolon();
+
+ return node.finishThrowStatement(argument);
+ }
+
+ // 12.14 The try statement
+
+ function parseCatchClause() {
+ var param, body, node = new Node();
+
+ expectKeyword('catch');
+
+ expect('(');
+ if (match(')')) {
+ throwUnexpectedToken(lookahead);
+ }
+
+ param = parseVariableIdentifier();
+ // 12.14.1
+ if (strict && isRestrictedWord(param.name)) {
+ tolerateError(Messages.StrictCatchVariable);
+ }
+
+ expect(')');
+ body = parseBlock();
+ return node.finishCatchClause(param, body);
+ }
+
+ function parseTryStatement(node) {
+ var block, handlers = [], finalizer = null;
+
+ expectKeyword('try');
+
+ block = parseBlock();
+
+ if (matchKeyword('catch')) {
+ handlers.push(parseCatchClause());
+ }
+
+ if (matchKeyword('finally')) {
+ lex();
+ finalizer = parseBlock();
+ }
+
+ if (handlers.length === 0 && !finalizer) {
+ throwError(Messages.NoCatchOrFinally);
+ }
+
+ return node.finishTryStatement(block, [], handlers, finalizer);
+ }
+
+ // 12.15 The debugger statement
+
+ function parseDebuggerStatement(node) {
+ expectKeyword('debugger');
+
+ consumeSemicolon();
+
+ return node.finishDebuggerStatement();
+ }
+
+ // 12 Statements
+
+ function parseStatement() {
+ var type = lookahead.type,
+ expr,
+ labeledBody,
+ key,
+ node;
+
+ if (type === Token.EOF) {
+ throwUnexpectedToken(lookahead);
+ }
+
+ if (type === Token.Punctuator && lookahead.value === '{') {
+ return parseBlock();
+ }
+
+ node = new Node();
+
+ if (type === Token.Punctuator) {
+ switch (lookahead.value) {
+ case ';':
+ return parseEmptyStatement(node);
+ case '(':
+ return parseExpressionStatement(node);
+ default:
+ break;
+ }
+ } else if (type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'break':
+ return parseBreakStatement(node);
+ case 'continue':
+ return parseContinueStatement(node);
+ case 'debugger':
+ return parseDebuggerStatement(node);
+ case 'do':
+ return parseDoWhileStatement(node);
+ case 'for':
+ return parseForStatement(node);
+ case 'function':
+ return parseFunctionDeclaration(node);
+ case 'if':
+ return parseIfStatement(node);
+ case 'return':
+ return parseReturnStatement(node);
+ case 'switch':
+ return parseSwitchStatement(node);
+ case 'throw':
+ return parseThrowStatement(node);
+ case 'try':
+ return parseTryStatement(node);
+ case 'var':
+ return parseVariableStatement(node);
+ case 'while':
+ return parseWhileStatement(node);
+ case 'with':
+ return parseWithStatement(node);
+ default:
+ break;
+ }
+ }
+
+ expr = parseExpression();
+
+ // 12.12 Labelled Statements
+ if ((expr.type === Syntax.Identifier) && match(':')) {
+ lex();
+
+ key = '$' + expr.name;
+ if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+ throwError(Messages.Redeclaration, 'Label', expr.name);
+ }
+
+ state.labelSet[key] = true;
+ labeledBody = parseStatement();
+ delete state.labelSet[key];
+ return node.finishLabeledStatement(expr, labeledBody);
+ }
+
+ consumeSemicolon();
+
+ return node.finishExpressionStatement(expr);
+ }
+
+ // 13 Function Definition
+
+ function parseFunctionSourceElements() {
+ var sourceElement, sourceElements = [], token, directive, firstRestricted,
+ oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount,
+ node = new Node();
+
+ expect('{');
+
+ while (index < length) {
+ if (lookahead.type !== Token.StringLiteral) {
+ break;
+ }
+ token = lookahead;
+
+ sourceElement = parseSourceElement();
+ sourceElements.push(sourceElement);
+ if (sourceElement.expression.type !== Syntax.Literal) {
+ // this is not directive
+ break;
+ }
+ directive = source.slice(token.start + 1, token.end - 1);
+ if (directive === 'use strict') {
+ strict = true;
+ if (firstRestricted) {
+ tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
+ }
+ } else {
+ if (!firstRestricted && token.octal) {
+ firstRestricted = token;
+ }
+ }
+ }
+
+ oldLabelSet = state.labelSet;
+ oldInIteration = state.inIteration;
+ oldInSwitch = state.inSwitch;
+ oldInFunctionBody = state.inFunctionBody;
+ oldParenthesisCount = state.parenthesizedCount;
+
+ state.labelSet = {};
+ state.inIteration = false;
+ state.inSwitch = false;
+ state.inFunctionBody = true;
+ state.parenthesizedCount = 0;
+
+ while (index < length) {
+ if (match('}')) {
+ break;
+ }
+ sourceElement = parseSourceElement();
+ if (typeof sourceElement === 'undefined') {
+ break;
+ }
+ sourceElements.push(sourceElement);
+ }
+
+ expect('}');
+
+ state.labelSet = oldLabelSet;
+ state.inIteration = oldInIteration;
+ state.inSwitch = oldInSwitch;
+ state.inFunctionBody = oldInFunctionBody;
+ state.parenthesizedCount = oldParenthesisCount;
+
+ return node.finishBlockStatement(sourceElements);
+ }
+
+ function validateParam(options, param, name) {
+ var key = '$' + name;
+ if (strict) {
+ if (isRestrictedWord(name)) {
+ options.stricted = param;
+ options.message = Messages.StrictParamName;
+ }
+ if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
+ options.stricted = param;
+ options.message = Messages.StrictParamDupe;
+ }
+ } else if (!options.firstRestricted) {
+ if (isRestrictedWord(name)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictParamName;
+ } else if (isStrictModeReservedWord(name)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictReservedWord;
+ } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
+ options.firstRestricted = param;
+ options.message = Messages.StrictParamDupe;
+ }
+ }
+ options.paramSet[key] = true;
+ }
+
+ function parseParam(options) {
+ var token, param, def;
+
+ token = lookahead;
+ param = parseVariableIdentifier();
+ validateParam(options, token, token.value);
+ if (match('=')) {
+ lex();
+ def = parseAssignmentExpression();
+ ++options.defaultCount;
+ }
+
+ options.params.push(param);
+ options.defaults.push(def);
+
+ return !match(')');
+ }
+
+ function parseParams(firstRestricted) {
+ var options;
+
+ options = {
+ params: [],
+ defaultCount: 0,
+ defaults: [],
+ firstRestricted: firstRestricted
+ };
+
+ expect('(');
+
+ if (!match(')')) {
+ options.paramSet = {};
+ while (index < length) {
+ if (!parseParam(options)) {
+ break;
+ }
+ expect(',');
+ }
+ }
+
+ expect(')');
+
+ if (options.defaultCount === 0) {
+ options.defaults = [];
+ }
+
+ return {
+ params: options.params,
+ defaults: options.defaults,
+ stricted: options.stricted,
+ firstRestricted: options.firstRestricted,
+ message: options.message
+ };
+ }
+
+ function parseFunctionDeclaration() {
+ var id, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, node = new Node();
+
+ expectKeyword('function');
+ token = lookahead;
+ id = parseVariableIdentifier();
+ if (strict) {
+ if (isRestrictedWord(token.value)) {
+ tolerateUnexpectedToken(token, Messages.StrictFunctionName);
+ }
+ } else {
+ if (isRestrictedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictFunctionName;
+ } else if (isStrictModeReservedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictReservedWord;
+ }
+ }
+
+ tmp = parseParams(firstRestricted);
+ params = tmp.params;
+ defaults = tmp.defaults;
+ stricted = tmp.stricted;
+ firstRestricted = tmp.firstRestricted;
+ if (tmp.message) {
+ message = tmp.message;
+ }
+
+ previousStrict = strict;
+ body = parseFunctionSourceElements();
+ if (strict && firstRestricted) {
+ throwUnexpectedToken(firstRestricted, message);
+ }
+ if (strict && stricted) {
+ tolerateUnexpectedToken(stricted, message);
+ }
+ strict = previousStrict;
+
+ return node.finishFunctionDeclaration(id, params, defaults, body);
+ }
+
+ function parseFunctionExpression() {
+ var token, id = null, stricted, firstRestricted, message, tmp,
+ params = [], defaults = [], body, previousStrict, node = new Node();
+
+ expectKeyword('function');
+
+ if (!match('(')) {
+ token = lookahead;
+ id = parseVariableIdentifier();
+ if (strict) {
+ if (isRestrictedWord(token.value)) {
+ tolerateUnexpectedToken(token, Messages.StrictFunctionName);
+ }
+ } else {
+ if (isRestrictedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictFunctionName;
+ } else if (isStrictModeReservedWord(token.value)) {
+ firstRestricted = token;
+ message = Messages.StrictReservedWord;
+ }
+ }
+ }
+
+ tmp = parseParams(firstRestricted);
+ params = tmp.params;
+ defaults = tmp.defaults;
+ stricted = tmp.stricted;
+ firstRestricted = tmp.firstRestricted;
+ if (tmp.message) {
+ message = tmp.message;
+ }
+
+ previousStrict = strict;
+ body = parseFunctionSourceElements();
+ if (strict && firstRestricted) {
+ throwUnexpectedToken(firstRestricted, message);
+ }
+ if (strict && stricted) {
+ tolerateUnexpectedToken(stricted, message);
+ }
+ strict = previousStrict;
+
+ return node.finishFunctionExpression(id, params, defaults, body);
+ }
+
+ // 14 Program
+
+ function parseSourceElement() {
+ if (lookahead.type === Token.Keyword) {
+ switch (lookahead.value) {
+ case 'const':
+ case 'let':
+ return parseConstLetDeclaration(lookahead.value);
+ case 'function':
+ return parseFunctionDeclaration();
+ default:
+ return parseStatement();
+ }
+ }
+
+ if (lookahead.type !== Token.EOF) {
+ return parseStatement();
+ }
+ }
+
+ function parseSourceElements() {
+ var sourceElement, sourceElements = [], token, directive, firstRestricted;
+
+ while (index < length) {
+ token = lookahead;
+ if (token.type !== Token.StringLiteral) {
+ break;
+ }
+
+ sourceElement = parseSourceElement();
+ sourceElements.push(sourceElement);
+ if (sourceElement.expression.type !== Syntax.Literal) {
+ // this is not directive
+ break;
+ }
+ directive = source.slice(token.start + 1, token.end - 1);
+ if (directive === 'use strict') {
+ strict = true;
+ if (firstRestricted) {
+ tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
+ }
+ } else {
+ if (!firstRestricted && token.octal) {
+ firstRestricted = token;
+ }
+ }
+ }
+
+ while (index < length) {
+ sourceElement = parseSourceElement();
+ /* istanbul ignore if */
+ if (typeof sourceElement === 'undefined') {
+ break;
+ }
+ sourceElements.push(sourceElement);
+ }
+ return sourceElements;
+ }
+
+ function parseProgram() {
+ var body, node;
+
+ skipComment();
+ peek();
+ node = new Node();
+ strict = false;
+
+ body = parseSourceElements();
+ return node.finishProgram(body);
+ }
+
+ function filterTokenLocation() {
+ var i, entry, token, tokens = [];
+
+ for (i = 0; i < extra.tokens.length; ++i) {
+ entry = extra.tokens[i];
+ token = {
+ type: entry.type,
+ value: entry.value
+ };
+ if (entry.regex) {
+ token.regex = {
+ pattern: entry.regex.pattern,
+ flags: entry.regex.flags
+ };
+ }
+ if (extra.range) {
+ token.range = entry.range;
+ }
+ if (extra.loc) {
+ token.loc = entry.loc;
+ }
+ tokens.push(token);
+ }
+
+ extra.tokens = tokens;
+ }
+
+ function tokenize(code, options) {
+ var toString,
+ tokens;
+
+ toString = String;
+ if (typeof code !== 'string' && !(code instanceof String)) {
+ code = toString(code);
+ }
+
+ source = code;
+ index = 0;
+ lineNumber = (source.length > 0) ? 1 : 0;
+ lineStart = 0;
+ length = source.length;
+ lookahead = null;
+ state = {
+ allowIn: true,
+ labelSet: {},
+ inFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ lastCommentStart: -1
+ };
+
+ extra = {};
+
+ // Options matching.
+ options = options || {};
+
+ // Of course we collect tokens here.
+ options.tokens = true;
+ extra.tokens = [];
+ extra.tokenize = true;
+ // The following two fields are necessary to compute the Regex tokens.
+ extra.openParenToken = -1;
+ extra.openCurlyToken = -1;
+
+ extra.range = (typeof options.range === 'boolean') && options.range;
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
+
+ if (typeof options.comment === 'boolean' && options.comment) {
+ extra.comments = [];
+ }
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
+ extra.errors = [];
+ }
+
+ try {
+ peek();
+ if (lookahead.type === Token.EOF) {
+ return extra.tokens;
+ }
+
+ lex();
+ while (lookahead.type !== Token.EOF) {
+ try {
+ lex();
+ } catch (lexError) {
+ if (extra.errors) {
+ extra.errors.push(lexError);
+ // We have to break on the first error
+ // to avoid infinite loops.
+ break;
+ } else {
+ throw lexError;
+ }
+ }
+ }
+
+ filterTokenLocation();
+ tokens = extra.tokens;
+ if (typeof extra.comments !== 'undefined') {
+ tokens.comments = extra.comments;
+ }
+ if (typeof extra.errors !== 'undefined') {
+ tokens.errors = extra.errors;
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ extra = {};
+ }
+ return tokens;
+ }
+
+ function parse(code, options) {
+ var program, toString;
+
+ toString = String;
+ if (typeof code !== 'string' && !(code instanceof String)) {
+ code = toString(code);
+ }
+
+ source = code;
+ index = 0;
+ lineNumber = (source.length > 0) ? 1 : 0;
+ lineStart = 0;
+ length = source.length;
+ lookahead = null;
+ state = {
+ allowIn: true,
+ labelSet: {},
+ parenthesisCount: 0,
+ inFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ lastCommentStart: -1
+ };
+
+ extra = {};
+ if (typeof options !== 'undefined') {
+ extra.range = (typeof options.range === 'boolean') && options.range;
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
+ extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
+
+ if (extra.loc && options.source !== null && options.source !== undefined) {
+ extra.source = toString(options.source);
+ }
+
+ if (typeof options.tokens === 'boolean' && options.tokens) {
+ extra.tokens = [];
+ }
+ if (typeof options.comment === 'boolean' && options.comment) {
+ extra.comments = [];
+ }
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
+ extra.errors = [];
+ }
+ if (extra.attachComment) {
+ extra.range = true;
+ extra.comments = [];
+ extra.bottomRightStack = [];
+ extra.trailingComments = [];
+ extra.leadingComments = [];
+ }
+ }
+
+ try {
+ program = parseProgram();
+ if (typeof extra.comments !== 'undefined') {
+ program.comments = extra.comments;
+ }
+ if (typeof extra.tokens !== 'undefined') {
+ filterTokenLocation();
+ program.tokens = extra.tokens;
+ }
+ if (typeof extra.errors !== 'undefined') {
+ program.errors = extra.errors;
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ extra = {};
+ }
+
+ return program;
+ }
+
+ // Sync with *.json manifests.
+ exports.version = '2.0.0';
+
+ exports.tokenize = tokenize;
+
+ exports.parse = parse;
+
+ // Deep copy.
+ /* istanbul ignore next */
+ exports.Syntax = (function () {
+ var name, types = {};
+
+ if (typeof Object.create === 'function') {
+ types = Object.create(null);
+ }
+
+ for (name in Syntax) {
+ if (Syntax.hasOwnProperty(name)) {
+ types[name] = Syntax[name];
+ }
+ }
+
+ if (typeof Object.freeze === 'function') {
+ Object.freeze(types);
+ }
+
+ return types;
+ }());
+
+}));
+/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/examples/js/controls/OrbitControls.js b/examples/js/controls/OrbitControls.js
index be5f768ec88da4..e150b589c64711 100644
--- a/examples/js/controls/OrbitControls.js
+++ b/examples/js/controls/OrbitControls.js
@@ -37,10 +37,14 @@ THREE.OrbitControls = function ( object, domElement ) {
this.noZoom = false;
this.zoomSpeed = 1.0;
- // Limits to how far you can dolly in and out
+ // Limits to how far you can dolly in and out ( PerspectiveCamera only )
this.minDistance = 0;
this.maxDistance = Infinity;
+ // Limits to how far you can zoom in and out ( OrthographicCamera only )
+ this.minZoom = 0;
+ this.maxZoom = Infinity;
+
// Set to true to disable this control
this.noRotate = false;
this.rotateSpeed = 1.0;
@@ -112,6 +116,7 @@ THREE.OrbitControls = function ( object, domElement ) {
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
+ this.zoom0 = this.object.zoom;
// so camera.up is the orbit axis
@@ -180,7 +185,7 @@ THREE.OrbitControls = function ( object, domElement ) {
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
- if ( scope.object.fov !== undefined ) {
+ if ( scope.object instanceof THREE.PerspectiveCamera ) {
// perspective
var position = scope.object.position;
@@ -194,7 +199,7 @@ THREE.OrbitControls = function ( object, domElement ) {
scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight );
scope.panUp( 2 * deltaY * targetDistance / element.clientHeight );
- } else if ( scope.object.top !== undefined ) {
+ } else if ( scope.object instanceof THREE.OrthographicCamera ) {
// orthographic
scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth );
@@ -217,7 +222,21 @@ THREE.OrbitControls = function ( object, domElement ) {
}
- scale /= dollyScale;
+ if ( scope.object instanceof THREE.PerspectiveCamera ) {
+
+ scale /= dollyScale;
+
+ } else if ( scope.object instanceof THREE.OrthographicCamera ) {
+
+ scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) );
+ scope.object.updateProjectionMatrix();
+ scope.dispatchEvent( changeEvent );
+
+ } else {
+
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+
+ }
};
@@ -229,7 +248,21 @@ THREE.OrbitControls = function ( object, domElement ) {
}
- scale *= dollyScale;
+ if ( scope.object instanceof THREE.PerspectiveCamera ) {
+
+ scale *= dollyScale;
+
+ } else if ( scope.object instanceof THREE.OrthographicCamera ) {
+
+ scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) );
+ scope.object.updateProjectionMatrix();
+ scope.dispatchEvent( changeEvent );
+
+ } else {
+
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+
+ }
};
@@ -315,6 +348,10 @@ THREE.OrbitControls = function ( object, domElement ) {
this.target.copy( this.target0 );
this.object.position.copy( this.position0 );
+ this.object.zoom = this.zoom0;
+
+ this.object.updateProjectionMatrix();
+ this.dispatchEvent( changeEvent );
this.update();
@@ -414,7 +451,7 @@ THREE.OrbitControls = function ( object, domElement ) {
scope.dollyIn();
- } else {
+ } else if ( dollyDelta.y < 0 ) {
scope.dollyOut();
@@ -473,7 +510,7 @@ THREE.OrbitControls = function ( object, domElement ) {
scope.dollyOut();
- } else {
+ } else if ( delta < 0 ) {
scope.dollyIn();
@@ -606,7 +643,7 @@ THREE.OrbitControls = function ( object, domElement ) {
scope.dollyOut();
- } else {
+ } else if ( dollyDelta.y < 0 ) {
scope.dollyIn();
diff --git a/examples/js/controls/TrackballControls.js b/examples/js/controls/TrackballControls.js
index 241df9a8ee27df..4525da14a1d3e5 100644
--- a/examples/js/controls/TrackballControls.js
+++ b/examples/js/controls/TrackballControls.js
@@ -26,11 +26,9 @@ THREE.TrackballControls = function ( object, domElement ) {
this.noRotate = false;
this.noZoom = false;
this.noPan = false;
- this.noRoll = false;
this.staticMoving = false;
this.dynamicDampingFactor = 0.2;
- this.cylindricalRotation = true;
this.minDistance = 0;
this.maxDistance = Infinity;
@@ -50,9 +48,6 @@ THREE.TrackballControls = function ( object, domElement ) {
_eye = new THREE.Vector3(),
- _rotateStart = new THREE.Vector3(),
- _rotateEnd = new THREE.Vector3(),
-
_movePrev = new THREE.Vector2(),
_moveCurr = new THREE.Vector2(),
@@ -141,7 +136,7 @@ THREE.TrackballControls = function ( object, domElement ) {
vector.set(
( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),
- ( ( _this.screen.height * 0.5 + _this.screen.top - pageY ) / ( _this.screen.height * 0.5 ) / _this.screen.width * _this.screen.height )
+ ( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional
);
return vector;
@@ -149,56 +144,6 @@ THREE.TrackballControls = function ( object, domElement ) {
}() );
- var getMouseProjectionOnBall = ( function () {
-
- var vector = new THREE.Vector3();
- var objectUp = new THREE.Vector3();
- var mouseOnBall = new THREE.Vector3();
-
- return function ( pageX, pageY ) {
-
- mouseOnBall.set(
- ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ),
- ( _this.screen.height * 0.5 + _this.screen.top - pageY ) / ( _this.screen.height * 0.5 ),
- 0.0
- );
-
- var length = mouseOnBall.length();
-
- if ( _this.noRoll ) {
-
- if ( length < Math.SQRT1_2 ) {
-
- mouseOnBall.z = Math.sqrt( 1.0 - length * length );
-
- } else {
-
- mouseOnBall.z = 0.5 / length;
-
- }
-
- } else if ( length > 1.0 ) {
-
- mouseOnBall.normalize();
-
- } else {
-
- mouseOnBall.z = Math.sqrt( 1.0 - length * length );
-
- }
-
- _eye.copy( _this.object.position ).sub( _this.target );
-
- vector.copy( _this.object.up ).setLength( mouseOnBall.y );
- vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
- vector.add( _eye.setLength( mouseOnBall.z ) );
-
- return vector;
-
- };
-
- }() );
-
this.rotateCamera = (function() {
var axis = new THREE.Vector3(),
@@ -211,80 +156,47 @@ THREE.TrackballControls = function ( object, domElement ) {
return function () {
- if ( _this.cylindricalRotation ) {
-
- moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
- angle = moveDirection.length();
-
- if ( angle ) {
-
- _eye.copy( _this.object.position ).sub( _this.target );
-
- eyeDirection.copy( _eye ).normalize();
- objectUpDirection.copy( _this.object.up ).normalize();
- objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
-
- objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
- objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
-
- moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
-
- axis.crossVectors( moveDirection, _eye ).normalize();
-
- angle *= _this.rotateSpeed;
- quaternion.setFromAxisAngle( axis, angle );
-
- _eye.applyQuaternion( quaternion );
- _this.object.up.applyQuaternion( quaternion );
-
- _lastAxis.copy( axis );
- _lastAngle = angle;
-
- }
- else if ( !_this.staticMoving && _lastAngle ) {
-
- _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
- _eye.copy( _this.object.position ).sub( _this.target );
- quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
- _eye.applyQuaternion( quaternion );
- _this.object.up.applyQuaternion( quaternion );
-
- }
-
- _movePrev.copy( _moveCurr );
-
- } else {
-
- angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
+ moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
+ angle = moveDirection.length();
- if ( angle ) {
+ if ( angle ) {
- axis.crossVectors( _rotateStart, _rotateEnd ).normalize();
+ _eye.copy( _this.object.position ).sub( _this.target );
- angle *= _this.rotateSpeed;
+ eyeDirection.copy( _eye ).normalize();
+ objectUpDirection.copy( _this.object.up ).normalize();
+ objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
- quaternion.setFromAxisAngle( axis, -angle );
+ objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
+ objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
- _eye.applyQuaternion( quaternion );
- _this.object.up.applyQuaternion( quaternion );
+ moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
- _rotateEnd.applyQuaternion( quaternion );
+ axis.crossVectors( moveDirection, _eye ).normalize();
- if ( _this.staticMoving ) {
+ angle *= _this.rotateSpeed;
+ quaternion.setFromAxisAngle( axis, angle );
- _rotateStart.copy( _rotateEnd );
+ _eye.applyQuaternion( quaternion );
+ _this.object.up.applyQuaternion( quaternion );
- } else {
+ _lastAxis.copy( axis );
+ _lastAngle = angle;
- quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
- _rotateStart.applyQuaternion( quaternion );
+ }
- }
+ else if ( !_this.staticMoving && _lastAngle ) {
- }
+ _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
+ _eye.copy( _this.object.position ).sub( _this.target );
+ quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
+ _eye.applyQuaternion( quaternion );
+ _this.object.up.applyQuaternion( quaternion );
}
+ _movePrev.copy( _moveCurr );
+
};
}());
@@ -491,17 +403,8 @@ THREE.TrackballControls = function ( object, domElement ) {
if ( _state === STATE.ROTATE && !_this.noRotate ) {
- if ( _this.cylindricalRotation ) {
-
- _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
- _movePrev.copy(_moveCurr);
-
- } else {
-
- _rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
- _rotateEnd.copy( _rotateStart );
-
- }
+ _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
+ _movePrev.copy(_moveCurr);
} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
@@ -531,16 +434,8 @@ THREE.TrackballControls = function ( object, domElement ) {
if ( _state === STATE.ROTATE && !_this.noRotate ) {
- if ( _this.cylindricalRotation ) {
-
- _movePrev.copy(_moveCurr);
- _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
-
- } else {
-
- _rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
-
- }
+ _movePrev.copy(_moveCurr);
+ _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
@@ -602,18 +497,8 @@ THREE.TrackballControls = function ( object, domElement ) {
case 1:
_state = STATE.TOUCH_ROTATE;
-
- if ( _this.cylindricalRotation ) {
-
- _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
- _movePrev.copy(_moveCurr);
-
- } else {
-
- _rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
- _rotateEnd.copy( _rotateStart );
-
- }
+ _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+ _movePrev.copy(_moveCurr);
break;
case 2:
@@ -647,16 +532,8 @@ THREE.TrackballControls = function ( object, domElement ) {
switch ( event.touches.length ) {
case 1:
- if ( _this.cylindricalRotation ) {
-
- _movePrev.copy(_moveCurr);
- _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
-
- } else {
-
- _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
-
- }
+ _movePrev.copy(_moveCurr);
+ _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
break;
case 2:
@@ -683,16 +560,8 @@ THREE.TrackballControls = function ( object, domElement ) {
switch ( event.touches.length ) {
case 1:
- if ( _this.cylindricalRotation ) {
-
- _movePrev.copy(_moveCurr);
- _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
-
- } else {
-
- _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
- _rotateStart.copy( _rotateEnd );
- }
+ _movePrev.copy(_moveCurr);
+ _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
break;
case 2:
diff --git a/examples/js/effects/VREffect.js b/examples/js/effects/VREffect.js
index 1c48e2fedec66e..324862850128fe 100644
--- a/examples/js/effects/VREffect.js
+++ b/examples/js/effects/VREffect.js
@@ -82,8 +82,8 @@ THREE.VREffect = function ( renderer, done ) {
var leftEyeTranslation = this.leftEyeTranslation;
var rightEyeTranslation = this.rightEyeTranslation;
var renderer = this._renderer;
- var rendererWidth = renderer.domElement.clientWidth;
- var rendererHeight = renderer.domElement.clientHeight;
+ var rendererWidth = renderer.context.drawingBufferWidth;
+ var rendererHeight = renderer.context.drawingBufferHeight;
var eyeDivisionLine = rendererWidth / 2;
renderer.enableScissorTest( true );
@@ -165,7 +165,7 @@ THREE.VREffect = function ( renderer, done ) {
}
if ( canvas.mozRequestFullScreen ) {
canvas.mozRequestFullScreen( { vrDisplay: vrHMD } );
- } else {
+ } else if ( canvas.webkitRequestFullscreen ) {
canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } );
}
};
diff --git a/examples/js/loaders/ColladaLoader.js b/examples/js/loaders/ColladaLoader.js
index fe6918622c464f..353ad00f6f0e83 100644
--- a/examples/js/loaders/ColladaLoader.js
+++ b/examples/js/loaders/ColladaLoader.js
@@ -3035,9 +3035,9 @@ THREE.ColladaLoader = function () {
} else if ( vcount === 4 ) {
- faces.push( new THREE.Face3( vs[0], vs[1], vs[3], [ ns[0], ns[1], ns[3]], cs.length ? [ cs[0], cs[1], cs[3]] : new THREE.Color() ) );
+ faces.push( new THREE.Face3( vs[0], vs[1], vs[3], [ ns[0].clone(), ns[1].clone(), ns[3].clone() ], cs.length ? [ cs[0], cs[1], cs[3] ] : new THREE.Color() ) );
- faces.push( new THREE.Face3( vs[1], vs[2], vs[3], [ ns[1], ns[2], ns[3]], cs.length ? [ cs[1], cs[2], cs[3]] : new THREE.Color() ) );
+ faces.push( new THREE.Face3( vs[1], vs[2], vs[3], [ ns[1].clone(), ns[2].clone(), ns[3].clone() ], cs.length ? [ cs[1], cs[2], cs[3] ] : new THREE.Color() ) );
} else if ( vcount > 4 && options.subdivideFaces ) {
@@ -3048,9 +3048,7 @@ THREE.ColladaLoader = function () {
for ( k = 1; k < vcount - 1; ) {
- // FIXME: normals don't seem to be quite right
-
- faces.push( new THREE.Face3( vs[0], vs[k], vs[k + 1], [ ns[0], ns[k ++], ns[k] ], clr ) );
+ faces.push( new THREE.Face3( vs[0], vs[k], vs[k + 1], [ ns[0].clone(), ns[k ++].clone(), ns[k].clone() ], clr ) );
}
diff --git a/examples/js/loaders/OBJLoader.js b/examples/js/loaders/OBJLoader.js
index 01d4f4c91509d8..f66baddcf25121 100644
--- a/examples/js/loaders/OBJLoader.js
+++ b/examples/js/loaders/OBJLoader.js
@@ -87,11 +87,12 @@ THREE.OBJLoader.prototype = {
}
- function addFace( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) {
+ function addFace( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) {
var ia = parseVertexIndex( a );
var ib = parseVertexIndex( b );
var ic = parseVertexIndex( c );
+ var id;
if ( d === undefined ) {
@@ -99,7 +100,7 @@ THREE.OBJLoader.prototype = {
} else {
- var id = parseVertexIndex( d );
+ id = parseVertexIndex( d );
addVertex( ia, ib, id );
addVertex( ib, ic, id );
@@ -108,9 +109,9 @@ THREE.OBJLoader.prototype = {
if ( ua !== undefined ) {
- var ia = parseUVIndex( ua );
- var ib = parseUVIndex( ub );
- var ic = parseUVIndex( uc );
+ ia = parseUVIndex( ua );
+ ib = parseUVIndex( ub );
+ ic = parseUVIndex( uc );
if ( d === undefined ) {
@@ -118,7 +119,7 @@ THREE.OBJLoader.prototype = {
} else {
- var id = parseUVIndex( ud );
+ id = parseUVIndex( ud );
addUV( ia, ib, id );
addUV( ib, ic, id );
@@ -129,9 +130,9 @@ THREE.OBJLoader.prototype = {
if ( na !== undefined ) {
- var ia = parseNormalIndex( na );
- var ib = parseNormalIndex( nb );
- var ic = parseNormalIndex( nc );
+ ia = parseNormalIndex( na );
+ ib = parseNormalIndex( nb );
+ ic = parseNormalIndex( nc );
if ( d === undefined ) {
@@ -139,7 +140,7 @@ THREE.OBJLoader.prototype = {
} else {
- var id = parseNormalIndex( nd );
+ id = parseNormalIndex( nd );
addNormal( ia, ib, id );
addNormal( ib, ic, id );
@@ -202,7 +203,7 @@ THREE.OBJLoader.prototype = {
var face_pattern3 = /f( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))?/;
- // f vertex//normal vertex//normal vertex//normal ...
+ // f vertex//normal vertex//normal vertex//normal ...
var face_pattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/
@@ -261,7 +262,7 @@ THREE.OBJLoader.prototype = {
} else if ( ( result = face_pattern2.exec( line ) ) !== null ) {
// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
-
+
addFace(
result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
@@ -337,8 +338,8 @@ THREE.OBJLoader.prototype = {
for ( var i = 0, l = objects.length; i < l; i ++ ) {
- var object = objects[ i ];
- var geometry = object.geometry;
+ object = objects[ i ];
+ geometry = object.geometry;
var buffergeometry = new THREE.BufferGeometry();
@@ -352,7 +353,7 @@ THREE.OBJLoader.prototype = {
buffergeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( geometry.uvs ), 2 ) );
}
- var material = new THREE.MeshLambertMaterial();
+ material = new THREE.MeshLambertMaterial();
material.name = object.material.name;
var mesh = new THREE.Mesh( buffergeometry, material );
diff --git a/examples/js/loaders/PLYLoader.js b/examples/js/loaders/PLYLoader.js
index da547209b1151f..d0734fe9c0cc6a 100644
--- a/examples/js/loaders/PLYLoader.js
+++ b/examples/js/loaders/PLYLoader.js
@@ -116,14 +116,17 @@ THREE.PLYLoader.prototype = {
var patternHeader = /ply([\s\S]*)end_header\s/;
var headerText = "";
- if ( ( result = patternHeader.exec( data ) ) !== null ) {
+ var headerLength = 0;
+ var result = patternHeader.exec( data );
+ if ( result !== null ) {
headerText = result [ 1 ];
+ headerLength = result[ 0 ].length;
}
var header = {
comments: [],
elements: [],
- headerLength: result[ 0 ].length
+ headerLength: headerLength
};
var lines = headerText.split( '\n' );
@@ -241,7 +244,7 @@ THREE.PLYLoader.prototype = {
parseASCIIElement: function ( properties, line ) {
- values = line.split( /\s+/ );
+ var values = line.split( /\s+/ );
var element = Object();
@@ -252,7 +255,7 @@ THREE.PLYLoader.prototype = {
var list = [];
var n = this.parseASCIINumber( values.shift(), properties[i].countType );
- for ( j = 0; j < n; j ++ ) {
+ for ( var j = 0; j < n; j ++ ) {
list.push( this.parseASCIINumber( values.shift(), properties[i].itemType ) );
@@ -354,7 +357,7 @@ THREE.PLYLoader.prototype = {
geometry.useColor = true;
- color = new THREE.Color();
+ var color = new THREE.Color();
color.setRGB( element.red / 255.0, element.green / 255.0, element.blue / 255.0 );
geometry.colors.push( color );
@@ -423,7 +426,7 @@ THREE.PLYLoader.prototype = {
var n = result[0];
read += result[1];
- for ( j = 0; j < n; j ++ ) {
+ for ( var j = 0; j < n; j ++ ) {
result = this.binaryRead( dataview, at + read, properties[i].itemType, little_endian );
list.push( result[0] );
diff --git a/examples/js/renderers/RaytracingRenderer.js b/examples/js/renderers/RaytracingRenderer.js
index 6c75c6090d5fa2..78a5b1ea02eb1b 100644
--- a/examples/js/renderers/RaytracingRenderer.js
+++ b/examples/js/renderers/RaytracingRenderer.js
@@ -9,6 +9,8 @@ THREE.RaytracingRenderer = function ( parameters ) {
parameters = parameters || {};
+ var scope = this;
+
var canvas = document.createElement( 'canvas' );
var context = canvas.getContext( '2d', {
alpha: parameters.alpha === true
@@ -458,7 +460,12 @@ THREE.RaytracingRenderer = function ( parameters ) {
blockX = 0;
blockY += blockSize;
- if ( blockY >= canvasHeight ) return;
+ if ( blockY >= canvasHeight ) {
+
+ scope.dispatchEvent( { type: "complete" } );
+ return;
+
+ }
}
@@ -535,3 +542,5 @@ THREE.RaytracingRenderer = function ( parameters ) {
};
};
+
+THREE.EventDispatcher.prototype.apply(THREE.RaytracingRenderer.prototype);
diff --git a/examples/js/shaders/ColorCorrectionShader.js b/examples/js/shaders/ColorCorrectionShader.js
index 20da4696f7f9bc..5d5253df2e7732 100644
--- a/examples/js/shaders/ColorCorrectionShader.js
+++ b/examples/js/shaders/ColorCorrectionShader.js
@@ -10,7 +10,8 @@ THREE.ColorCorrectionShader = {
"tDiffuse": { type: "t", value: null },
"powRGB": { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) },
- "mulRGB": { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
+ "mulRGB": { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) },
+ "addRGB": { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) }
},
@@ -33,13 +34,14 @@ THREE.ColorCorrectionShader = {
"uniform sampler2D tDiffuse;",
"uniform vec3 powRGB;",
"uniform vec3 mulRGB;",
+ "uniform vec3 addRGB;",
"varying vec2 vUv;",
"void main() {",
"gl_FragColor = texture2D( tDiffuse, vUv );",
- "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );",
+ "gl_FragColor.rgb = mulRGB * pow( ( gl_FragColor.rgb + addRGB ), powRGB );",
"}"
diff --git a/examples/misc_controls_trackball.html b/examples/misc_controls_trackball.html
index d6a7dd4687b89b..910491a311c209 100644
--- a/examples/misc_controls_trackball.html
+++ b/examples/misc_controls_trackball.html
@@ -35,8 +35,7 @@