2
0
Эх сурвалжийг харах

Merge branch 'dev' of [email protected]:mrdoob/three.js into phong_diffuseColor

Conflicts:
	examples/js/ShaderSkin.js
	examples/js/ShaderTerrain.js
	examples/js/shaders/NormalDisplacementShader.js
	src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
	src/renderers/shaders/ShaderChunk/linear_to_gamma_fragment.glsl
	src/renderers/shaders/ShaderChunk/map_fragment.glsl
	src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl
Ben Houston 10 жил өмнө
parent
commit
3e239215a6
100 өөрчлөгдсөн 3602 нэмэгдсэн , 1987 устгасан
  1. 1 1
      LICENSE
  2. 3 2
      bower.json
  3. 242 103
      build/three.js
  4. 210 203
      build/three.min.js
  5. 1 1
      docs/api/cameras/CubeCamera.html
  6. 3 1
      docs/api/constants/CustomBlendingEquations.html
  7. 1 1
      docs/api/constants/GLState.html
  8. 14 3
      docs/api/constants/Textures.html
  9. 54 23
      docs/api/core/Object3D.html
  10. 89 9
      docs/api/core/Raycaster.html
  11. 1 1
      docs/api/extras/ImageUtils.html
  12. 6 4
      docs/api/extras/geometries/CylinderGeometry.html
  13. 3 3
      docs/api/extras/helpers/ArrowHelper.html
  14. 1 1
      docs/api/extras/helpers/BoundingBoxHelper.html
  15. 45 0
      docs/api/extras/helpers/BoxHelper.html
  16. 8 8
      docs/api/extras/helpers/DirectionalLightHelper.html
  17. 21 15
      docs/api/extras/helpers/EdgesHelper.html
  18. 23 11
      docs/api/extras/helpers/FaceNormalsHelper.html
  19. 1 0
      docs/api/extras/helpers/GridHelper.html
  20. 1 0
      docs/api/extras/helpers/PointLightHelper.html
  21. 23 11
      docs/api/extras/helpers/VertexNormalsHelper.html
  22. 22 12
      docs/api/extras/helpers/VertexTangentsHelper.html
  23. 24 15
      docs/api/extras/helpers/WireframeHelper.html
  24. 26 31
      docs/api/lights/DirectionalLight.html
  25. 9 34
      docs/api/lights/SpotLight.html
  26. 2 3
      docs/api/loaders/ColladaLoader.html
  27. 1 1
      docs/api/loaders/OBJMTLLoader.html
  28. 0 114
      docs/api/loaders/SceneLoader.html
  29. 1 6
      docs/api/materials/MeshLambertMaterial.html
  30. 2 7
      docs/api/materials/MeshPhongMaterial.html
  31. 1 1
      docs/api/materials/SpriteMaterial.html
  32. 8 0
      docs/api/math/Color.html
  33. 141 124
      docs/api/math/Euler.html
  34. 10 0
      docs/api/math/Matrix4.html
  35. 8 5
      docs/api/math/Quaternion.html
  36. 14 1
      docs/api/math/Vector2.html
  37. 14 1
      docs/api/math/Vector3.html
  38. 14 6
      docs/api/math/Vector4.html
  39. 5 0
      docs/api/objects/Line.html
  40. 6 0
      docs/api/objects/Mesh.html
  41. 5 0
      docs/api/objects/PointCloud.html
  42. 1 1
      docs/api/renderers/WebGLRenderTarget.html
  43. 2 2
      docs/api/renderers/WebGLRenderer.html
  44. 1 1
      docs/list.js
  45. 4 4
      docs/manual/introduction/Creating-a-scene.html
  46. 119 123
      docs/scenes/js/material.js
  47. 41 17
      editor/css/dark.css
  48. 30 14
      editor/css/light.css
  49. 12 6
      editor/css/main.css
  50. 168 0
      editor/examples/arkanoid.app.json
  51. 168 0
      editor/examples/camera.app.json
  52. 97 0
      editor/examples/particles.app.json
  53. 134 0
      editor/examples/pong.app.json
  54. 56 15
      editor/index.html
  55. 6 5
      editor/js/Config.js
  56. 132 11
      editor/js/Editor.js
  57. 29 4
      editor/js/Menubar.Add.js
  58. 6 2
      editor/js/Menubar.Edit.js
  59. 61 0
      editor/js/Menubar.Examples.js
  60. 27 61
      editor/js/Menubar.File.js
  61. 1 1
      editor/js/Menubar.Play.js
  62. 34 0
      editor/js/Menubar.View.js
  63. 1 0
      editor/js/Menubar.js
  64. 11 3
      editor/js/Player.js
  65. 91 0
      editor/js/Script.js
  66. 2 2
      editor/js/Sidebar.Geometry.BufferGeometry.js
  67. 2 2
      editor/js/Sidebar.Geometry.Geometry.js
  68. 2 2
      editor/js/Sidebar.Geometry.js
  69. 28 39
      editor/js/Sidebar.Material.js
  70. 74 9
      editor/js/Sidebar.Object3D.js
  71. 27 12
      editor/js/Sidebar.Project.js
  72. 4 4
      editor/js/Sidebar.Scene.js
  73. 0 46
      editor/js/Sidebar.Script.Editor.js
  74. 80 13
      editor/js/Sidebar.Script.js
  75. 1 1
      editor/js/Sidebar.js
  76. 0 2
      editor/js/Toolbar.js
  77. 27 16
      editor/js/Viewport.js
  78. 188 46
      editor/js/libs/app.js
  79. 22 14
      editor/js/libs/codemirror/codemirror.css
  80. 344 229
      editor/js/libs/codemirror/codemirror.js
  81. 8 8
      editor/js/libs/codemirror/mode/javascript.js
  82. 31 0
      editor/js/libs/codemirror/theme/monokai.css
  83. 1 0
      editor/js/libs/sortable.min.js
  84. 0 75
      editor/js/libs/ui.editor.js
  85. 31 177
      editor/js/libs/ui.js
  86. 176 0
      editor/js/libs/ui.three.js
  87. 1 0
      examples/canvas_ascii_effect.html
  88. 1 2
      examples/canvas_lines_colors_2d.html
  89. 1 1
      examples/canvas_lines_dashed.html
  90. 6 4
      examples/index.html
  91. 2 1
      examples/js/Mirror.js
  92. 4 3
      examples/js/Ocean.js
  93. 3 5
      examples/js/ShaderDeferred.js
  94. 26 35
      examples/js/ShaderSkin.js
  95. 10 21
      examples/js/ShaderTerrain.js
  96. 0 4
      examples/js/controls/EditorControls.js
  97. 0 61
      examples/js/controls/OculusControls.js
  98. 0 6
      examples/js/controls/OrbitControls.js
  99. 194 105
      examples/js/controls/OrthographicTrackballControls.js
  100. 10 10
      examples/js/controls/TransformControls.js

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 The MIT License
 
-Copyright © 2010-2014 three.js authors
+Copyright © 2010-2015 three.js authors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

+ 3 - 2
bower.json

@@ -1,6 +1,6 @@
 {
 	"name": "three.js",
-	"version": "0.0.69",
+	"version": "0.0.70",
 	"homepage": "http://threejs.org/",
 	"description": "JavaScript 3D library",
 	"main": "build/three.js",
@@ -17,7 +17,8 @@
 		"*.md",
 		"docs",
 		"editor",
-		"examples",
+		"examples/*",
+		"!examples/js",
 		"src",
 		"test",
 		"utils",

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 242 - 103
build/three.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 210 - 203
build/three.min.js


+ 1 - 1
docs/api/cameras/CubeCamera.html

@@ -24,7 +24,7 @@
 		scene.add( cubeCamera );
 		
 		//Create car
-		var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, ambient: 0xffffff, envMap: cubeCamera.renderTarget } );
+		var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeCamera.renderTarget } );
 		var car = new Mesh( carGeometry, chromeMaterial );
 		scene.add( car );
 		

+ 3 - 1
docs/api/constants/CustomBlendingEquations.html

@@ -13,7 +13,9 @@
 		<div>
 		THREE.AddEquation<br />
 		THREE.SubtractEquation<br />
-		THREE.ReverseSubtractEquation
+		THREE.ReverseSubtractEquation<br />
+		THREE.MinEquation<br />
+		THREE.MaxEquation
 		</div>
 
 		<h2>Destination Factors</h2>

+ 1 - 1
docs/api/constants/GLState.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="../../page.css" />
 	</head>
 	<body>
-		<h1>GL State Conflicts</h1>
+		<h1>GL State Constants</h1>
 
 		<h2>Cull Face</h2>
 		<div>

+ 14 - 3
docs/api/constants/Textures.html

@@ -21,6 +21,8 @@
 		THREE.UVMapping<br />
 		THREE.CubeReflectionMapping<br />
 		THREE.CubeRefractionMapping<br />
+		THREE.EquirectangularReflectionMapping<br />
+		THREE.EquirectangularRefractionMapping<br />
 		THREE.SphericalReflectionMapping
 		</div>
 
@@ -49,7 +51,8 @@
 		THREE.UnsignedShortType<br />
 		THREE.IntType<br />
 		THREE.UnsignedIntType<br />
-		THREE.FloatType
+		THREE.FloatType<br />
+		THREE.HalfFloatType
 		</div>
 
 		<h2>Pixel Types</h2>
@@ -65,10 +68,11 @@
 		THREE.RGBFormat<br />
 		THREE.RGBAFormat<br />
 		THREE.LuminanceFormat<br />
-		THREE.LuminanceAlphaFormat
+		THREE.LuminanceAlphaFormat<br />
+		THREE.RGBEFormat
 		</div>
 
-		<h2>Compressed Texture Formats</h2>
+		<h2>DDS / ST3C Compressed Texture Formats</h2>
 		<div>
 		THREE.RGB_S3TC_DXT1_Format<br />
 		THREE.RGBA_S3TC_DXT1_Format<br />
@@ -76,6 +80,13 @@
 		THREE.RGBA_S3TC_DXT5_Format
 		</div>
 
+		<h2>PVRTC Compressed Texture Formats</h2>
+		<div>
+		THREE.RGB_PVRTC_4BPPV1_Format<br />
+		THREE.RGB_PVRTC_2BPPV1_Format<br />
+		THREE.RGBA_PVRTC_4BPPV1_Format<br />
+		THREE.RGBA_PVRTC_2BPPV1_Format
+		</div>
 
 		<h2>Source</h2>
 

+ 54 - 23
docs/api/core/Object3D.html

@@ -25,7 +25,7 @@
 
 		<h3>[property:Integer id]</h3>
 		<div>
-		Unique number for this object instance.
+		readonly – Unique number for this object instance.
 		</div>
 
 		<h3>[property:String uuid]</h3>
@@ -59,11 +59,6 @@
 		Object's local rotation (<a href="https://en.wikipedia.org/wiki/Euler_angles" target="_blank">Euler angles</a>), in radians.
 		</div>
 
-		<h3>[property:String eulerOrder]</h3>
-		<div>
-		Order of axis for Euler angles.
-		</div>
-
 		<h3>[property:Vector3 scale]</h3>
 		<div>
 		Object's local scale.
@@ -81,48 +76,64 @@
 
 		<h3>[property:Quaternion quaternion]</h3>
 		<div>
-		Object's local rotation as [page:Quaternion Quaternion]. Only used when useQuaternion is set to true.
-		</div>
-
-		<h3>[property:Boolean useQuaternion]</h3>
-		<div>
-		Use quaternion instead of Euler angles for specifying local rotation.
+		Object's local rotation as [page:Quaternion Quaternion].
 		</div>
 
 		<h3>[property:Boolean visible]</h3>
 		<div>
 		Object gets rendered if *true*.
 		</div>
+		<div>
+		default – true
+		</div>
 
 		<h3>[property:Boolean castShadow]</h3>
 		<div>
 		Gets rendered into shadow map.
 		</div>
+		<div>
+		default – false
+		</div>
 
 		<h3>[property:Boolean receiveShadow]</h3>
 		<div>
 		Material gets baked in shadow receiving.
 		</div>
+		<div>
+		default – false
+		</div>
 
 		<h3>[property:Boolean frustumCulled]</h3>
 		<div>
 		When this is set, it checks every frame if the object is in the frustum of the camera. Otherwise the object gets drawn every frame even if it isn't visible.
 		</div>
+		<div>
+		default – true
+		</div>
 
 		<h3>[property:Boolean matrixAutoUpdate]</h3>
 		<div>
 		When this is set, it calculates the matrix of position, (rotation or quaternion) and scale every frame and also recalculates the matrixWorld property.
 		</div>
+		<div>
+		default – true
+		</div>
 
 		<h3>[property:Boolean matrixWorldNeedsUpdate]</h3>
 		<div>
 		When this is set, it calculates the matrixWorld in that frame and resets this property to false.
 		</div>
+		<div>
+		default – false
+		</div>
 
 		<h3>[property:Boolean rotationAutoUpdate]</h3>
 		<div>
 		When this is set, then the rotationMatrix gets calculated every frame.
 		</div>
+		<div>
+		default – true
+		</div>
 
 		<h3>[property:object userData]</h3>
 		<div>
@@ -195,29 +206,46 @@
 		Rotates object to face point in space.
 		</div>
 
-		<h3>[method:null add]( [page:Object3D object] )</h3>
+		<h3>[method:null add]( [page:Object3D object], ... )</h3>
 		<div>
 		object - An object.<br />
 		</div>
 		<div>
-		Adds *object* as child of this object.
+		Adds *object* as child of this object. An arbitrary number of objects may be added.
 		</div>
 
-		<h3>[method:null remove]( [page:Object3D object] )</h3>
+		<h3>[method:null remove]( [page:Object3D object], ... )</h3>
 		<div>
 		object - An object.<br />
 		</div>
 		<div>
-		Removes *object* as child of this object.
+		Removes *object* as child of this object. An arbitrary number of objects may be removed.
 		</div>
 
 		<h3>[method:null traverse]( [page:Function callback] )</h3>
 		<div>
-		callback - An Function with as first argument an object3D object.<br />
+		callback - A function with as first argument an object3D object.<br />
 		</div>
 		<div>
 		Executes the callback on this object and all descendants.
 		</div>
+		
+		<h3>[method:null traverseVisible]( [page:Function callback] )</h3>
+		<div>
+		callback - A function with as first argument an object3D object.<br />
+		</div>
+		<div>
+		Like traverse, but the callback will only be executed for visible objects.
+		Descendants of invisible objects are not traversed.
+		</div>
+		
+		<h3>[method:null traverseAncestors]( [page:Function callback] )</h3>
+		<div>
+		callback - A function with as first argument an object3D object.<br />
+		</div>
+		<div>
+		Executes the callback on this object and all ancestors.
+		</div>
 
 		<h3>[method:null updateMatrix]()</h3>
 		<div>
@@ -235,22 +263,20 @@
 		</div>
 
 
-		<h3>[method:Object3D getObjectByName]([page:String name], [page:Boolean recursive])</h3>
+		<h3>[method:Object3D getObjectByName]([page:String name])</h3>
 		<div>
 		name -- String to match to the children's Object3d.name property. <br />
-		recursive -- Boolean whether to search through the children's children. Default is false.
 		</div>
 		<div>
-		Searches through the object's children and returns the first with a matching name, optionally recursive.
+		Searches through the object's children and returns the first with a matching name.
 		</div>
 
-		<h3>[method:Object3D getObjectById]([page:Integer id], [page:Boolean recursive])</h3>
+		<h3>[method:Object3D getObjectById]([page:Integer id])</h3>
 		<div>
 		id -- Unique number of the object instance<br />
-		recursive -- Boolean whether to search through the children's children. Default is false.
 		</div>
 		<div>
-		Searches through the object's children and returns the first with a matching id, optionally recursive.
+		Searches through the object's children and returns the first with a matching id.
 		</div>
 
 		<h3>[method:Object3D translateOnAxis]([page:Vector3 axis], [page:Float distance])</h3>
@@ -271,6 +297,11 @@
 		Rotate an object along an axis in object space. The axis is assumed to be normalized.
 		</div>
 
+		<h3>[method:Array raycast]([page:Raycaster raycaster], [page:Array intersects])</h3>
+		<div>
+		Abstract method to get intersections between a casted ray and this object. Subclasses such as [page:Mesh], [page:Line], and [page:PointCloud] implement this method in order to participate in raycasting.
+		</div>
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 89 - 9
docs/api/core/Raycaster.html

@@ -11,18 +11,67 @@
 
 		<div class="desc">
 		This class makes raycasting easier. Raycasting is used for picking and more.
+		</div>
+
+		<h2>Example</h2>
+		<code>
+		var raycaster = new THREE.Raycaster();
+		var mouse = new THREE.Vector2();
+
+		function onMouseMove( event ) {
+
+			// calculate mouse position in normalized device coordinates
+			// (-1 to +1) for both components
+
+			mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
+			mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;		
+		
+		}
+
+		function render() {
+
+			// update the picking ray with the camera and mouse position	
+			raycaster.setFromCamera( mouse, camera );	
+
+			// calculate objects intersecting the picking ray
+			var intersects = raycaster.intersectObjects( scene.children );
+
+			for ( var i = 0; i < intersects.length; i++ ) {
+
+				intersects[ i ].object.material.color.set( 0xff0000 );
 			
+			}
+			
+			renderer.render( scene, camera );
+
+		}
+
+		window.addEventListener( 'mousemove', onMouseMove, false );
+
+		window.requestAnimationFrame(render);
+
+		</code>
+		<div>Examples: [example:webgl_interactive_cubes Raycasting to a Mesh], 
+			[example:webgl_interactive_cubes_ortho Raycasting to a Mesh in using an OrthographicCamera], 
+			[example:webgl_interactive_buffergeometry Raycasting to a Mesh with BufferGeometry], 
+			[example:webgl_interactive_lines Raycasting to a Line], 
+			[example:webgl_interactive_raycasting_pointcloud Raycasting to a PointCloud], 
+			[example:webgl_geometry_terrain_raycast Terrain raycasting], 
+			[example:webgl_octree_raycasting Raycasting using an octree],
+			[example:webgl_interactive_voxelpainter Raycasting to paint voxels]</div>
+
+
+		<div>
 		</div>
 
 
 		<h2>Constructor</h2>
 
-
 		<h3>[name]( [page:Vector3 origin], [page:Vector3 direction], [page:Float near], [page:Float far] ) {</h3>
 		<div>
 		[page:Vector3 origin] — The origin vector where the ray casts from.<br />
 		[page:Vector3 direction] — The direction vector that  gives direction to the ray.<br />
-		[page:Float near] — All results returned are further away then near. Near can't be negative. Default value is 0.<br />
+		[page:Float near] — All results returned are further away than near. Near can't be negative. Default value is 0.<br />
 		[page:Float far] — All results returned are closer then far. Far can't be lower then near . Default value is Infinity.
 		</div>
 		<div>
@@ -51,7 +100,12 @@
 
 		<h3>[property:float precision]</h3>
 		<div>
-		The precision factor of the raycaster. 
+		The precision factor of the raycaster when intersecting [page:Mesh] objects. 
+		</div>
+
+		<h3>.[page:float linePrecision]</h3>
+		<div>
+		The precision factor of the raycaster when intersecting [page:Line] objects. 
 		</div>
 
 		<h2>Methods</h2>
@@ -65,16 +119,45 @@
 		Updates the ray with a new origin and direction.
 		</div>
 
+		<h3>[method:null setFromCamera]( [page:Vector2 coords], [page:Camera camera] )</h3>
+		<div>
+		[page:Vector2 coords] — 2D coordinates of the mouse, in normalized device coordinates (NDC)---X and Y components should be between -1 and 1.<br />
+		[page:Camera camera] — camera from which the ray should originate
+		</div>
+		<div>
+		Updates the ray with a new origin and direction.
+		</div>
+
+
 		<h3>[method:Array intersectObject]( [page:Object3D object], [page:Boolean recursive] )</h3>
 		<div>
+		<p>
 		[page:Object3D object] — The object to check for intersection with the ray.<br />
 		[page:Boolean recursive] — If set, it also checks all descendants. Otherwise it only checks intersecton with the object.
+		</p>
 		</div>
 		<div>
-		checks all intersection between the ray and the object with or without the descendants. Intersections are returned sorted by distance, closest first.
+		Checks all intersection between the ray and the object with or without the descendants. Intersections are returned sorted by distance, closest first. An array of intersections is returned...
         <code>
-            [ { distance, point, face, faceIndex, object }, ... ]
+            [ { distance, point, face, faceIndex, indices, object }, ... ]
         </code>
+        <p>
+        [page:Float distance] – distance between the origin of the ray and the intersection<br />
+        [page:Vector3 point] – point of intersection, in world coordinates<br />
+        [page:Face3 face] – intersected face<br />
+        [page:Integer faceIndex] – index of the intersected face<br />
+        [page:Array indices] – indices of vertices comprising the intersected face<br />
+        [page:Object3D object] – the intersected object
+    	</p>
+        <p>
+        When intersecting a [page:Mesh] with a [page:BufferGeometry], the *faceIndex* will be *undefined*, and *indices* will be set; when intersecting a [page:Mesh] with a [page:Geometry], *indices* will be *undefined*. 
+        </p>
+		<p>
+		*Raycaster* delegates to the [page:Object3D.raycast raycast] method of the passed object, when evaluating whether the ray intersects the object or not. This allows [page:Mesh meshes] to respond differently to ray casting than [page:Line lines] and [page:PointCloud pointclouds].
+		</p>
+		<p>
+		*Note* that for meshes, faces must be pointed towards the origin of the [page:.ray ray] in order to be detected; intersections of the ray passing through the back of a face will not be detected. To raycast against both faces of an object, you'll want to set the [page:Mesh.material material]'s [page:Material.side side] property to *THREE.DoubleSide*.  
+		</p>
 		</div>
 
 		<h3>[method:Array intersectObjects]( [page:Array objects], [page:Boolean recursive] )</h3>
@@ -83,10 +166,7 @@
 		[page:Boolean recursive] — If set, it also checks all descendants of the objects. Otherwise it only checks intersecton with the objects.
 		</div>
 		<div>
-		checks all intersection between the ray and the objects with or without the descendants. Intersections are returned sorted by distance, closest first.
-        <code>
-            [ { distance, point, face, faceIndex, object }, ... ]
-        </code>
+		Checks all intersection between the ray and the objects with or without the descendants. Intersections are returned sorted by distance, closest first. Intersections are of the same form as those returned by [page:.intersectObject].
 		</div>
 
 

+ 1 - 1
docs/api/extras/ImageUtils.html

@@ -58,7 +58,7 @@
 		<h3>[method:todo loadTexture]([page:String url], [page:UVMapping mapping], [page:Function onLoad], [page:Function onError])</h3>
 		<div>
 		url -- the url of the texture<br />
-		mapping -- Can be an instance of [page:UVMapping THREE.UVMapping], [page:CubeReflectionMapping THREE.CubeReflectionMapping] or [page:SphericalReflectionMapping THREE.SphericalReflectionMapping]. Describes how the image is applied to the object.<br />Use undefined instead of null as a default value. See mapping property of [page:Texture texture] for more details.
+		mapping -- Can be an instance of [page:UVMapping THREE.UVMapping], [page:CubeReflectionMapping THREE.CubeReflectionMapping] or [page:SphericalReflectionMapping THREE.SphericalReflectionMapping]. Describes how the image is applied to the object.<br />Use undefined instead of null as a default value. See mapping property of [page:Texture texture] for more details. <br/>
 		onLoad -- callback function<br />
 		onError -- callback function
 		</div>

+ 6 - 4
docs/api/extras/geometries/CylinderGeometry.html

@@ -8,7 +8,7 @@
 	</head>
 	<body>
 		[page:Geometry] &rarr;
-		
+
 		<h1>[name]</h1>
 
 		<div class="desc">A class for generating cylinder geometries</div>
@@ -26,21 +26,23 @@
 		<h2>Constructor</h2>
 
 
-		<h3>[name]([page:Float radiusTop], [page:Float radiusBottom], [page:Float height], [page:Integer radiusSegments], [page:Integer heightSegments], [page:Boolean openEnded])</h3>
+		<h3>[name]([page:Float radiusTop], [page:Float radiusBottom], [page:Float height], [page:Integer radiusSegments], [page:Integer heightSegments], [page:Boolean openEnded], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<div>
 		radiusTop — Radius of the cylinder at the top. Default is 20.<br />
 		radiusBottom — Radius of the cylinder at the bottom. Default is 20.<br />
 		height — Height of the cylinder. Default is 100.<br />
 		radiusSegments — Number of segmented faces around the circumference of the cylinder. Default is 8<br />
 		heightSegments — Number of rows of faces along the height of the cylinder. Default is 1.<br />
-		openEnded — A Boolean indicating whether the ends of the cylinder are open or capped. Default is false, meaning capped.
+		openEnded — A Boolean indicating whether the ends of the cylinder are open or capped. Default is false, meaning capped.<br />
+		thetaStart — Start angle for first segment, default = 0 (three o'clock position).<br />
+		thetaLength — The central angle, often called theta, of the circular sector. The default is 2*Pi, which makes for a complete cylinder.
 		</div>
 
 
 		<h2>Properties</h2>
 
 		<div>
-		Each of the contructor parameters is accessible as a property of the same name. Any modification of these properties after instantiation does not change the geometry.
+		Each of the constructor parameters is accessible as a property of the same name. Any modification of these properties after instantiation does not change the geometry.
 		</div>
 
 

+ 3 - 3
docs/api/extras/helpers/ArrowHelper.html

@@ -74,15 +74,15 @@
 		<div>
 		length -- The desired length<br />
 		headLength -- The length of the head of the arrow<br />
-		headWidth -- The length of the width of the arrow		
+		headWidth -- The length of the width of the arrow
 		</div>
 		<div>
 		Sets the length of the arrowhelper.
 		</div>
 
-		<h3>[method:null setDirection]([page:vector3 dir])</h3>
+		<h3>[method:null setDirection]([page:Vector3 dir])</h3>
 		<div>
-		dir -- The desired direction in euler format.
+		dir -- The desired direction. Must be a unit vector.
 		</div>
 		<div>
 		Sets the direction of the arrowhelper.

+ 1 - 1
docs/api/extras/helpers/BoundingBoxHelper.html

@@ -26,7 +26,7 @@
 		bbox.update();
 		scene.add( bbox );
 		</code>
-
+		<div>Note that this helper will create a wireframe [page:Mesh] object with a [page:BoxGeometry]; the resulting bounding box object will therefore have face diagonals. You may want to use [page:BoxHelper], which generates a [page:Line] object without face diagonals.</div>
 
 
 		<h2>Constructor</h2>

+ 45 - 0
docs/api/extras/helpers/BoxHelper.html

@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<script src="../../../list.js"></script>
+		<script src="../../../page.js"></script>
+		<link type="text/css" rel="stylesheet" href="../../../page.css" />
+	</head>
+	<body>
+		[page:Line] &rarr;
+		
+		<h1>[name]</h1>
+
+		<div class="desc">Helper object to show a wireframe box (with no face diagonals) around an object</div>
+
+
+		<h2>Example</h2>
+
+		<code>var sphere = new THREE.SphereGeometry();
+		var object = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial(0xff0000) );
+		var box = new THREE.BoxHelper( object );
+		scene.add( box );
+		</code>
+
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [page:Object3D object] )</h3>
+		<div>Creates a new wireframe box matching the size of the passed box.</div>
+
+		<h2>Properties</h2>
+
+		<div>(none)</div>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null update]( [page:Object3D object] )</h3>
+		<div>
+		Updates the helper's geometry to match the dimensions of the [page:Geometry.boundingBox bounding box] of the passed object's geometry.
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 8 - 8
docs/api/extras/helpers/DirectionalLightHelper.html

@@ -11,26 +11,26 @@
 		
 		<h1>[name]</h1>
 
-		<div class="desc">todo</div>
+		<div class="desc">Visualize a [page:DirectionalLight]'s effect on the scene</div>
 
 
 		<h2>Constructor</h2>
 
 
-		<h3>[name]([page:todo light], [page:todo sphereSize])</h3>
+		<h3>[name]([DirectionalLight:todo light], [page:Number size])</h3>
 		<div>
-		light -- todo <br />
-		sphereSize -- todo
+		light -- [page:DirectionalLight] -- Light to visualize <br />
+		size -- dimensions of the plane
 		</div>
 		<div>
-		todo
+		Creates a line and plane to visualize the light's position and direction
 		</div>
 
 
 		<h2>Properties</h2>
 		
 
-		<h3>[property:Mesh lightSphere]</h3>
+		<h3>[property:Line lightPlane]</h3>
 		<div>
 		todo
 		</div> 
@@ -48,9 +48,9 @@
 		<h2>Methods</h2>
 
 
-		<h3>.update() [page:todo]</h3>
+		<h3>.[method:null update]()</h3>
 		<div>
-		todo
+		Updates the helper to match the position and direction of the [page:.light].
 		</div>
 
 		<h2>Source</h2>

+ 21 - 15
docs/api/extras/helpers/EdgesHelper.html

@@ -11,36 +11,42 @@
 		
 		<h1>[name]</h1>
 
-		<div class="desc">todo</div>
+		<div class="desc">Creates a wireframe object that shows the "hard" edges of another object's geometry. To draw a full wireframe image of an object, see [page:WireframeHelper].</div>
 
 		<h2>Example</h2>
 
-		<code>todo</code>
+		<code>
+		geometry = new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 );
+		material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
+		object = new THREE.Mesh( geometry, material );
 
-		<h2>Constructor</h2>
+		edges = new THREE.EdgesHelper( object, 0x00ff00 );
 
+		scene.add( object );
+		scene.add( edges );
+		</code>
 
-		<h3>todo</h3>
-		<div></div>
+		<h2>Constructor</h2>
+		<h3>[name]( [page:Object3D object], [page:Color color] )</h3>
+		<div>
+		object -- Object of which to draw edges <br />
+		color -- Color of the edges.
+		</div>
+		<div>
+		Creates a [page:Line], showing only the "hard" edges of the passed object; specifically, no edge will be drawn between faces which are adjacent and coplanar (or nearly coplanar).
+		</div>
 
 
 		<h2>Properties</h2>
 
-		<h3>todo</h3>
-		<div>
-		todo
-		</div> 
+		<div>none</div>
 
 
 		<h2>Methods</h2>
 		
-
-		<h3>todo</h3>
-		<div>todo</div>
-		<div>
-		todo
-		</div>
+		<div>none</div>
 		
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 23 - 11
docs/api/extras/helpers/FaceNormalsHelper.html

@@ -11,35 +11,47 @@
 		
 		<h1>[name]</h1>
 
-		<div class="desc">todo</div>
+		<div class="desc">Renders [page:ArrowHelper arrows] to visualize an object's [page:Face3 face] normals. Requires that the object's geometry be an instance of [page:Geometry] (does not work with [page:BufferGeometry]), and that face normals have been specified on all [page:Face3 faces] or calculated with [page:Geometry.computeFaceNormals computeFaceNormals].</div>
 
 		<h2>Example</h2>
 
-		<code>todo</code>
+		<code>
+		geometry = new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 );
+		material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
+		object = new THREE.Mesh( geometry, material );
+
+		edges = new THREE.FaceNormalsHelper( object, 2, 0x00ff00, 1 );
+
+		scene.add( object );
+		scene.add( edges );
+		</code>
+		[example:webgl_helpers Example using various helpers]
 
 		<h2>Constructor</h2>
 
 
-		<h3>todo</h3>
-		<div></div>
+		<h3>[name]( [page:Object3D object], [page:Number size], [page:Color color], [page:Number linewidth] )</h3>
+		<div>object -- object for which to render face normals
+		size -- size (length) of the arrows
+		color -- color of the arrows
+		linewidth -- width of the arrow lines
+		</div>
 
 
 		<h2>Properties</h2>
 
-		<h3>todo</h3>
+		<h3>[property:Object3D object]</h3>
 		<div>
-		todo
+		The attached object
 		</div> 
 
 
 		<h2>Methods</h2>
 		
 
-		<h3>todo</h3>
-		<div>todo</div>
-		<div>
-		todo
-		</div>
+		<h3>[method:null update]()</h3>
+		<div>Updates the face normal preview based on movement of the object.</div>
+
 		
 		<h2>Source</h2>
 

+ 1 - 0
docs/api/extras/helpers/GridHelper.html

@@ -22,6 +22,7 @@
 		var gridHelper = new THREE.GridHelper( size, step );		
 		scene.add( gridHelper );
 		</code>
+		[example:webgl_helpers Example using various helpers]
 
 
 		<h2>Constructor</h2>

+ 1 - 0
docs/api/extras/helpers/PointLightHelper.html

@@ -24,6 +24,7 @@
 		var pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
 		scene.add( pointLightHelper );
 		</code>
+		[example:webgl_helpers Example using various helpers]
 
 
 		<h2>Constructor</h2>

+ 23 - 11
docs/api/extras/helpers/VertexNormalsHelper.html

@@ -11,35 +11,47 @@
 		
 		<h1>[name]</h1>
 
-		<div class="desc">todo</div>
+		<div class="desc">Renders [page:ArrowHelper arrows] to visualize an object's vertex normal vectors. Requires that normals have been specified in a [page:BufferAttribute custom attribute] or have been calculated using [page:Geometry.computeVertexNormals computeVertexNormals]. </div>
 
 		<h2>Example</h2>
 
-		<code>todo</code>
+		<code>
+		geometry = new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 );
+		material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
+		object = new THREE.Mesh( geometry, material );
+
+		edges = new THREE.VertexNormalsHelper( object, 2, 0x00ff00, 1 );
+
+		scene.add( object );
+		scene.add( edges );
+		</code>
+		[example:webgl_helpers Example using various helpers]
 
 		<h2>Constructor</h2>
 
 
-		<h3>todo</h3>
-		<div></div>
+		<h3>[name]( [page:Object3D object], [page:Number size], [page:Color color], [page:Number linewidth] )</h3>
+		<div>object -- object for which to render vertex normals
+		size -- size (length) of the arrows
+		color -- color of the arrows
+		linewidth -- width of the arrow lines
+		</div>
 
 
 		<h2>Properties</h2>
 
-		<h3>todo</h3>
+		<h3>[property:Object3D object]</h3>
 		<div>
-		todo
+		The attached object
 		</div> 
 
 
 		<h2>Methods</h2>
 		
 
-		<h3>todo</h3>
-		<div>todo</div>
-		<div>
-		todo
-		</div>
+		<h3>[method:null update]()</h3>
+		<div>Updates the vertex normal preview based on movement of the object.</div>
+
 		
 		<h2>Source</h2>
 

+ 22 - 12
docs/api/extras/helpers/VertexTangentsHelper.html

@@ -11,36 +11,46 @@
 		
 		<h1>[name]</h1>
 
-		<div class="desc">todo</div>
+		<div class="desc">Renders [page:ArrowHelper arrows] to visualize an object's vertex tangent vectors. Requires that tangents have been specified in a [page:BufferAttribute custom attribute] or have been computed using [page:Geometry.computeTangents computeTangents]. </div>
 
 		<h2>Example</h2>
 
-		<code>todo</code>
+		<code>
+		geometry = new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 );
+		material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
+		object = new THREE.Mesh( geometry, material );
+
+		edges = new THREE.VertexTangentsHelper( object, 2, 0x00ff00, 1 );
+
+		scene.add( object );
+		scene.add( edges );
+		</code>
 
 		<h2>Constructor</h2>
 
 
-		<h3>todo</h3>
-		<div></div>
+		<h3>[name]( [page:Object3D object], [page:Number size], [page:Color color], [page:Number linewidth] )</h3>
+		<div>object -- object for which to render vertex tangents
+		size -- size (length) of the arrows
+		color -- color of the arrows
+		linewidth -- width of the arrow lines
+		</div>
 
 
 		<h2>Properties</h2>
 
-		<h3>todo</h3>
+		<h3>[property:Object3D object]</h3>
 		<div>
-		todo
+		The attached object
 		</div> 
 
 
 		<h2>Methods</h2>
 		
 
-		<h3>todo</h3>
-		<div>todo</div>
-		<div>
-		todo
-		</div>
-		
+		<h3>[method:null update]()</h3>
+		<div>Updates the vertex tangent preview arrows based on the new position and tangents of the object.</div>
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 24 - 15
docs/api/extras/helpers/WireframeHelper.html

@@ -11,36 +11,45 @@
 		
 		<h1>[name]</h1>
 
-		<div class="desc">todo</div>
+		<div class="desc">Creates a wireframe object that shows the edges of another object's geometry. To draw a  wireframe image showing only "hard" edges (edges between non-coplanar faces), see [page:EdgesHelper].</div>
 
 		<h2>Example</h2>
 
-		<code>todo</code>
+		<code>
+		geometry = new THREE.BoxGeometry( 10, 10, 10, 2, 2, 2 );
+		material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
+		object = new THREE.Mesh( geometry, material );
 
-		<h2>Constructor</h2>
+		wireframe = new THREE.WireframeHelper( object, 0x00ff00 );
+
+		scene.add( object );
+		scene.add( wireframe );
 
+		</code>
+		[example:webgl_helpers Example using various helpers], [example:webgl_materials_wireframe Alternative approach using a shader.]
 
-		<h3>todo</h3>
-		<div></div>
+		<h2>Constructor</h2>
+		<h3>[name]( [page:Object3D object], [page:Color color] )</h3>
+		<div>
+		object -- Object of which to draw edges <br />
+		color -- Color of the edges.
+		</div>
+		<div>
+		Creates a [page:Line], showing only the edges between vertices of an object.
+		</div>
 
 
 		<h2>Properties</h2>
 
-		<h3>todo</h3>
-		<div>
-		todo
-		</div> 
+		<div>none</div>
 
 
 		<h2>Methods</h2>
 		
-
-		<h3>todo</h3>
-		<div>todo</div>
-		<div>
-		todo
-		</div>
+		<div>none</div>
 		
+
+		<h2>Source</h2>
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 26 - 31
docs/api/lights/DirectionalLight.html

@@ -103,7 +103,7 @@ scene.add( directionalLight );</code>
 
 		<h3>[property:Float shadowBias]</h3>
 		<div>
-			Shadow map bias.<br />
+			Shadow map bias, how much to add or subtract from the normalized depth when deciding whether a surface is in shadow.<br />
 			Default — *0*.
 		</div>
 
@@ -127,81 +127,76 @@ scene.add( directionalLight );</code>
 
 		<h3>[property:Boolean shadowCascade]</h3>
 		<div>
-			??? <br />
+			**Experimental** If true, use a series of shadow maps in a cascade. This can give better z-depth resolution for a directional light. <br />
 			Default — *false*.
 		</div>
 
-		<h3>[property:Vector3 shadowCascadeOffset]</h3>
+		<h3>[property:Integer shadowCascadeCount]</h3>
 		<div>
-			??? <br />
-			Default — *Three.Vector3( 0, 0, -1000 )*.
+			Number of shadow maps to allocate in a cascade (one after another). <br />
+			Default — *2*.
 		</div>
 
-		<h3>[property:Integer shadowCascadeCount]</h3>
+		<h3>[property:Vector3 shadowCascadeOffset]</h3>
 		<div>
-			??? <br />
-			Default — *2*.
+			A relative position to real camera where virtual shadow cameras are attached. A magic vector; scene and light orientation dependent. <br />
+			Default — *Three.Vector3( 0, 0, -1000 )*.
 		</div>
 
 		<h3>[property:Array shadowCascadeBias]</h3>
 		<div>
-			??? <br />
+			An array of shadowMapBias values for the corresponding shadow map in the cascade, near to far. <br />
 			Default — <strong>[ 0, 0, 0 ]</strong>.
 		</div>
 
 		<h3>[property:Array shadowCascadeWidth]</h3>
 		<div>
-			??? <br />
+			An array of shadowMapWidth values for the corresponding shadow map in the cascade, near to far. <br />
 			Default — <strong>[ 512, 512, 512 ]</strong>.
 		</div>
 
 		<h3>[property:Array shadowCascadeHeight]</h3>
 		<div>
-			??? <br />
+			An array of shadowMapHeight values for the corresponding shadow map in the cascade, near to far. <br />
 			Default — <strong>[ 512, 512, 512 ]</strong>.
 		</div>
 
 		<h3>[property:Array shadowCascadeNearZ]</h3>
 		<div>
-			??? <br />
+			An array of shadowMapNear values for the corresponding shadow map in the cascade, near to far. These typically start with -1.0 (near plane) and match with the previous shadowCascadeFarZ array value.<br />
 			Default — <strong>[ -1.000, 0.990, 0.998 ]</strong>.
 		</div>
 
 		<h3>[property:Array shadowCascadeFarZ]</h3>
 		<div>
-			??? <br />
+			An array of shadowMapFar values for the corresponding shadow map in the cascade, near to far. These typically match with the next shadowCascadeNearZ array value, ending in 1.0.<br />
 			Default — <strong>[ 0.990, 0.998, 1.000 ]</strong>.
 		</div>
 
 		<h3>[property:Array shadowCascadeArray]</h3>
 		<div>
-			??? <br />
-			Default — <strong>[ ]</strong>.
+			Array of size shadowCascadeCount of [page:DirectionalLight THREE.DirectionalLight] objects. This holds the series of separate shadow maps in a cascade, near to far. Created internally.
 		</div>
 
-		<h3>[property:RenderTarget shadowMap]</h3>
+		<h3>[property:Vector2 shadowMapSize]</h3>
 		<div>
-			??? <br />
-			Default — *null*.
-		</div>
+			The shadowMapWidth and shadowMapHeight stored in a [page:Vector2 THREE.Vector2]. Set internally during rendering.
+		</div> 
 
-		<h3>[property:Integer shadowMapSize]</h3>
+		<h3>[property:OrthographicCamera shadowCamera]</h3>
 		<div>
-			??? <br />
-			Default — *null*.
-		</div>
+			The shadow's view of the world. Computed internally during rendering from the shadowCamera* settings.
+		</div> 
 
-		<h3>[property:Camera shadowCamera]</h3>
+		<h3>[property:Matrix4 shadowMatrix]</h3>
 		<div>
-			??? <br />
-			Default — *null*.
-		</div>
+			Model to shadow camera space, to compute location and depth in shadow map. Computed internally during rendering.
+		</div> 
 
-		<h3>[property:Matrix shadowMatrix]</h3>
+		<h3>[property:WebGLRenderTarget shadowMap]</h3>
 		<div>
-			??? <br />
-			Default — *null*.
-		</div>
+		    The depth map generated using the shadowCamera; a location beyond a pixel's depth is in shadow. Computed internally during rendering.
+		</div> 
 		
 		<h2>Methods</h2>
 

+ 9 - 34
docs/api/lights/SpotLight.html

@@ -121,7 +121,7 @@ scene.add( spotLight );</code>
 		
 		<h3>[property:Float shadowBias]</h3>
 		<div>
-			Shadow map bias.<br />
+			Shadow map bias, how much to add or subtract from the normalized depth when deciding whether a surface is in shadow.<br />
 			Default — *0*.
 		</div>
 
@@ -143,49 +143,24 @@ scene.add( spotLight );</code>
 			Default — *512*.
 		</div>
 		
-		<h3>[property:Float shadowBias]</h3>
-		<div>
-			Shadow map bias.<br />
-			Default — *0*.
-		</div>
-
-		<h3>[property:Float shadowDarkness]</h3>
-		<div>
-			Darkness of shadow casted by this light (from *0* to *1*).<br />
-			Default — *0.5*.
-		</div>
-
-		<h3>[property:Integer shadowMapWidth]</h3>
-		<div>
-			Shadow map texture width in pixels.<br />
-			Default — *512*.
-		</div>
-
-		<h3>[property:Integer shadowMapHeight]</h3>
-		<div>
-			Shadow map texture height in pixels.<br />
-			Default — *512*.
-		</div>
-
-
-		<h3>[property:object shadowMatrix]</h3>
+		<h3>[property:Vector2 shadowMapSize]</h3>
 		<div>
-		todo
+			The shadowMapWidth and shadowMapHeight stored in a [page:Vector2 THREE.Vector2]. Set internally during rendering.
 		</div> 
 
-		<h3>[property:object shadowMapSize]</h3>
+		<h3>[property:PerspectiveCamera shadowCamera]</h3>
 		<div>
-		todo
+			The shadow's view of the world. Computed internally during rendering from the shadowCamera* settings.
 		</div> 
 
-		<h3>[property:object shadowCamera]</h3>
+		<h3>[property:Matrix4 shadowMatrix]</h3>
 		<div>
-		todo
+			Model to shadow camera space, to compute location and depth in shadow map. Computed internally during rendering.
 		</div> 
 
-		<h3>[property:object shadowMap]</h3>
+		<h3>[property:WebGLRenderTarget shadowMap]</h3>
 		<div>
-		todo
+		    The depth map generated using the shadowCamera; a location beyond a pixel's depth is in shadow. Computed internally during rendering.
 		</div> 
 
 		<h2>Methods</h2>		

+ 2 - 3
docs/api/loaders/ColladaLoader.html

@@ -10,7 +10,7 @@
 
 		<h1>[name]</h1>
 
-		<div class="desc">A loader for loading an <em>.babylon</em> resource.</div>
+		<div class="desc">A loader for <em>Collada</em> files.</div>
 
 
 		<h2>Constructor</h2>
@@ -86,7 +86,6 @@
 		// instantiate a loader
 		var loader = new THREE.ColladaLoader();
 
-		// load a Babylon resource
 		loader.load(
 			// resource URL
 			'models/collada/monster/monster.dae',
@@ -109,6 +108,6 @@
 
 		<h2>Source</h2>
 
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js examples/js/loaders/BabylonLoader.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/ColladaLoader.js examples/js/loaders/ColladaLoader.js]
 	</body>
 </html>

+ 1 - 1
docs/api/loaders/OBJMTLLoader.html

@@ -47,7 +47,7 @@
 		</div>
 		<div>
 		Parse an <em>obj</em> text structure and return an [page:Object3D].<br />
-		Found objects are converted to [page:Mesh] with a [page:BufferGeometry] and materials are converted to [page:MeshLambertMaterial].
+		Found objects are converted to a [page:Mesh] and materials are converted to [page:MeshLambertMaterial].
 		</div>
 
 		<h2>Example</h2>

+ 0 - 114
docs/api/loaders/SceneLoader.html

@@ -1,114 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<script src="../../list.js"></script>
-		<script src="../../page.js"></script>
-		<link type="text/css" rel="stylesheet" href="../../page.css" />
-	</head>
-	<body>
-
-		<h1>[name]</h1>
-
-		<div class="desc">A loader for loading a [page:Scene] from a <em>JSON</em> resource.</div>
-
-
-		<h2>Constructor</h2>
-
-		<h3>[name]( [page:LoadingManager manager] )</h3>
-		<div>
-		[page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
-		</div>
-		<div>
-		Creates a new [name].
-		</div>
-
-		<h2>Properties</h2>
-
-
-		<h2>Methods</h2>
-
-		<h3>[method:null load]( [page:String url], [page:Function onLoad], [page:Function onProgress], [page:Function onError] )</h3>
-		<div>
-		[page:String url] — required<br />
-		[page:Function onLoad] — Will be called when load completes. The argument will be an [page:Object] containing the loaded components.<br />
-		[page:Function onProgress] — Will be called while load progresses. The argument will be the XmlHttpRequest instance, that contain .[page:Integer total] and .[page:Integer loaded] bytes.<br />
-		[page:Function onError] — Will be called when load errors.<br />
-		</div>
-		<div>
-		Begin loading from url and call onLoad with the parsed scene.
-		</div>
-
-		<h3>[method:Object parse]( [page:Object json], [page:Function callbackFinished], [page:String url] )</h3>
-		<div>
-		[page:Object json] — The <em>JSON</em> structure to parse.<br />
-		[page:Function callbackFinished] — Will be called when parse completes.<br />
-		[page:String url] — Will be used as base for assets' relative URLs.<br />
-		</div>
-		<div>
-		Parse a <em>JSON</em> scene description and return a new [page:Object] with fully instantiated Three.js objects.
-		</div>
-
-		<h3>[method:null setCrossOrigin]( [page:String value] )</h3>
-		<div>
-		[page:String value] — The crossOrigin string to implement CORS for loading the url from a different domain that allows CORS.
-		</div>
-
-		<h3>[method:null addGeometryHandler]( [page:String typeID], [page:Function loaderClass] )</h3>
-		<div>
-		[page:String typeID] — The type to handle.<br />
-		[page:Function loaderClass] — The handler class.<br />
-		</div>
-		<div>
-		Add an handler for a specific geometry type.
-		</div>
-
-		<h3>[method:null addHierarchyHandler]( [page:String typeID], [page:Function loaderClass] )</h3>
-		<div>
-		[page:String typeID] — The type to handle.<br />
-		[page:Function loaderClass] — The handler class.<br />
-		</div>
-		<div>
-		Add an handler for a specific object type.
-		</div>
-
-
-		<h2>Example</h2>
-
-		<code>
-		// instantiate a loader
-		var loader = new THREE.SceneLoader();
-
-		// Handle STL geometries
-		loader.addGeometryHandler( "stl", THREE.STLLoader );
-
-		// Handle OBJ objects
-		loader.addHierarchyHandler( "obj", THREE.OBJLoader );
-
-		// load a JSON resource
-		loader.load(
-			// resource URL
-			'scenes/test_scene.js',
-			// Function when resource is loaded
-			function ( result ) {
-				scene.add( result.scene );
-			},
-			// Function called when download progresses
-			function ( xhr ) {
-				console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
-			},
-			// Function called when download errors
-			function ( xhr ) {
-				console.log( 'An error happened' );
-			}
-		);
-		</code>
-
-		[example:webgl_loader_scene]
-
-
-		<h2>Source</h2>
-
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/SceneLoader.js examples/js/loaders/SceneLoader.js]
-	</body>
-</html>

+ 1 - 6
docs/api/materials/MeshLambertMaterial.html

@@ -29,7 +29,7 @@
 		specularMap — Set specular map. Default is null.<br />
 		alphaMap — Set alpha map. Default is null.<br />
 		envMap — Set env map. Default is null.<br />
-		fog — Define whether the material color is affected by global fog settings. Default is false.
+		fog — Define whether the material color is affected by global fog settings. Default is false.<br />
 		shading — How the triangles of a curved surface are rendered. Default is [page:Materials THREE.SmoothShading].<br/>
 		wireframe — Render geometry as wireframe. Default is false (i.e. render as smooth shaded).<br/>
 		wireframeLinewidth — Controls wireframe thickness. Default is 1.<br/>
@@ -49,11 +49,6 @@
 		Diffuse color of the material. Default is white.<br />
 		</div>
 
-		<h3>[property:Color ambient]</h3>
-		<div>
-		Ambient color of the material, multiplied by the color of the [page:AmbientLight]. Default is white.<br />
-		</div>
-
 		<h3>[property:Color emissive]</h3>
 		<div>
 		Emissive (light) color of the material, essentially a solid color unaffected by other lighting. Default is black.<br />

+ 2 - 7
docs/api/materials/MeshPhongMaterial.html

@@ -41,7 +41,7 @@
 		</div>
 		<div>
 		Example:<br>
-		materials.push( new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.FlatShading } ) );
+		materials.push( new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.FlatShading } ) );
 	
 		</div>
 
@@ -54,11 +54,6 @@
 		Diffuse color of the material. Default is white.<br />
 		</div>
 
-		<h3>[property:Color ambient]</h3>
-		<div>
-		Ambient color of the material, multiplied by the color of the [page:AmbientLight]. Default is white.<br />
-		</div>
-
 		<h3>[property:Color emissive]</h3>
 		<div>
 		Emissive (light) color of the material, essentially a solid color unaffected by other lighting. Default is black.<br />
@@ -70,7 +65,7 @@
 		</div>
 
 		<h3>[property:Float shininess]</h3>
-		<div>How shiny the specular highlight is; a higher value gives a sharper highlight. Default is *30*.</div>
+		<div>How shiny the specular highlight is; a higher value gives a sharper highlight. Default is *30*. It should not be set to 0.</div>
 
 		<h3>[property:boolean metal]</h3>
 		<div>

+ 1 - 1
docs/api/materials/SpriteMaterial.html

@@ -24,7 +24,7 @@
 		<div>
 		color - color of the sprite<br/>
 		map - the texture map<br/>
-		rotation - the rotation of the sprite
+		rotation - the rotation of the sprite<br/>
 		fog - whether or not to use the scene fog<br/>
 		</div>
 

+ 8 - 0
docs/api/math/Color.html

@@ -176,6 +176,14 @@
 		Linear interpolation of this colors rgb values and the rgb values of the first argument. The alpha argument can be thought of as the percent between the two colors, where 0 is this color and 1 is the first argument.
 		</div>
 
+		<h3>[method:Array toArray]( [page:Array array] )</h3>
+		<div>
+		array -- Optional array to store the color.
+		</div>
+		<div>
+		Returns an array [r,g,b]
+		</div>
+
 		<h3>[method:Color equals]( [page:Color c] ) [page:Color this]</h3>
 		<div>
 		Compares this color and c and returns true if they are the same, false otherwise.

+ 141 - 124
docs/api/math/Euler.html

@@ -1,127 +1,144 @@
 <!DOCTYPE html>
 <html lang="en">
-  <head>
-    <meta charset="utf-8" />
-    <script src="../../list.js"></script>
-    <script src="../../page.js"></script>
-    <link type="text/css" rel="stylesheet" href="../../page.css" />
-  </head>
-  <body>
-    <h1>[name]</h1>
-
-    <div class="desc">Euler Angles. <br/><br/>
-    
-    Euler angles describe a rotation transformation by rotating an object on its various axes in specified amounts per axis, and a specified axis order.
-    (More information on <a href='http://en.wikipedia.org/wiki/Euler_angles' target='blank'>Wikipedia</a>)</div>
-
-    <h2>Example</h2>
-
-    <code>var a = new THREE.Euler( 0, 1, 1.57, 'XYZ' );
-    var b = new THREE.Vector3( 1, 0, 1 );
-    b.applyEuler(a);
-    </code>
-
-
-    <h2>Constructor</h2>
-
-
-    <h3>[name]( [page:Float x], [page:Float y], [page:Float z], [page:String order] )</h3>
-    <div>
-    x -- [page:Float] the angle of the x axis in radians<br />
-    y -- [page:Float] the angle of the y axis in radians<br />
-    z -- [page:Float] the angle of the z axis in radians<br />
-    order -- [page:String] A string representing the order that the rotations are applied, defaults to 'XYZ' (must be upper case).
-    </div>
-    <div>
-    A euler angle for transforming
-    </div>
-
-
-    <h2>Properties</h2>
-
-    <h3>[property:Float x]</h3>
-
-    <h3>[property:Float y]</h3>
-
-    <h3>[property:Float z]</h3>
-
-    <h3>[property:String order]</h3>
-
-
-
-    <h2>Methods</h2>
-
-    <h3>[method:Euler set]( [page:Float x], [page:Float y], [page:Float z], [page:String order] ) [page:Euler this]</h3>
-    <div>
-    x -- [page:Float] Angle in x axis in radians<br />
-    y -- [page:Float] Angle in y axis in radians<br />
-    z -- [page:Float] Angle in z axis in radians<br />
-    order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
-    </div>
-    <div>
-    Sets the angles of this euler transform.
-    </div>
-
-    <h3>[method:Euler copy]( [page:Euler euler] ) [page:Euler this]</h3>
-    <div>
-    Copies value of *euler* to this euler.
-    </div>
-
-    <h3>[method:Euler setFromRotationMatrix]( [page:Matrix4 m], [page:String order] ) [page:Euler this]</h3>
-    <div>
-    m -- [page:Matrix4] assumes upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled)<br />
-    order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
-    </div>
-    <div>
-    Sets the angles of this euler transform from a pure rotation matrix based on the orientation specified by order.
-    </div>
-
-    <h3>[method:Euler setFromQuaternion]( [page:Quaternion q], [page:String order] ) [page:Euler this]</h3>
-    <div>
-    q -- [page:Quaternion] quaternion must be normalized<br />
-    order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
-    </div>
-    <div>
-    Sets the angles of this euler transform from a normalized quaternion based on the orientation specified by order.
-    </div>
-
-    <h3>[method:Euler reorder]( [page:String newOrder] ) [page:Euler this]</h3>
-    <div>
-    Resets the euler angle with a new order by creating a quaternion from this euler angle and then setting this euler angle with the quaternion and the new order. <br />
-    WARNING: this discards revolution information.
-    </div>
-
-    <h3>[method:Euler fromArray]([page:Array array]) [page:Euler this]</h3>
-    <div>
-    array -- [page:Array] of length 3 or 4. array[3] is an optional order argument.
-    </div>
-    <div>
-    Assigns this euler's x angle to array[0]. <br />
-    Assigns this euler's y angle to array[1]. <br />
-    Assigns this euler's z angle to array[2]. <br />
-    Optionally assigns this euler's order to array[3].
-    </div>
-
-    <h3>[method:Array toArray]()</h3>
-    <div>
-    Returns an array [x, y, z, order].
-    </div>
-
-    <h3>[method:Boolean equals]( [page:Euler euler] )</h3>
-    <div>
-    Checks for strict equality of this euler and *euler*.
-    </div>
-
-    <h3>[method:Euler clone]()</h3>
-    <div>
-    Returns a new euler created from this euler.
-    </div>
-
-
-
-
-    <h2>Source</h2>
-
-    [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-  </body>
+	<head>
+		<meta charset="utf-8" />
+		<script src="../../list.js"></script>
+		<script src="../../page.js"></script>
+		<link type="text/css" rel="stylesheet" href="../../page.css" />
+	</head>
+	<body>
+		<h1>[name]</h1>
+
+		<div class="desc">Euler Angles. <br/><br/>
+
+		Euler angles describe a rotation transformation by rotating an object on its various axes in specified amounts per axis, and a specified axis order.
+		(More information on <a href='http://en.wikipedia.org/wiki/Euler_angles' target='blank'>Wikipedia</a>)</div>
+
+		<h2>Example</h2>
+
+		<code>var a = new THREE.Euler( 0, 1, 1.57, 'XYZ' );
+		var b = new THREE.Vector3( 1, 0, 1 );
+		b.applyEuler(a);
+		</code>
+
+
+		<h2>Constructor</h2>
+
+
+		<h3>[name]( [page:Float x], [page:Float y], [page:Float z], [page:String order] )</h3>
+		<div>
+		x -- [page:Float] the angle of the x axis in radians<br />
+		y -- [page:Float] the angle of the y axis in radians<br />
+		z -- [page:Float] the angle of the z axis in radians<br />
+		order -- [page:String] A string representing the order that the rotations are applied, defaults to 'XYZ' (must be upper case).
+		</div>
+		<div>
+		A euler angle for transforming
+		</div>
+
+
+		<h2>Properties</h2>
+
+		<h3>[property:Float x]</h3>
+
+		<h3>[property:Float y]</h3>
+
+		<h3>[property:Float z]</h3>
+
+		<h3>[property:String order]</h3>
+
+
+
+		<h2>Methods</h2>
+
+		<h3>[method:Euler set]( [page:Float x], [page:Float y], [page:Float z], [page:String order] ) [page:Euler this]</h3>
+		<div>
+		x -- [page:Float] Angle in x axis in radians<br />
+		y -- [page:Float] Angle in y axis in radians<br />
+		z -- [page:Float] Angle in z axis in radians<br />
+		order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
+		</div>
+		<div>
+		Sets the angles of this euler transform.
+		</div>
+
+		<h3>[method:Euler copy]( [page:Euler euler] ) [page:Euler this]</h3>
+		<div>
+		Copies value of *euler* to this euler.
+		</div>
+
+		<h3>[method:Euler setFromRotationMatrix]( [page:Matrix4 m], [page:String order] ) [page:Euler this]</h3>
+		<div>
+		m -- [page:Matrix4] assumes upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled)<br />
+		order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
+		</div>
+		<div>
+		Sets the angles of this euler transform from a pure rotation matrix based on the orientation specified by order.
+		</div>
+
+		<h3>[method:Euler setFromQuaternion]( [page:Quaternion q], [page:String order] ) [page:Euler this]</h3>
+		<div>
+		q -- [page:Quaternion] quaternion must be normalized<br />
+		order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
+		</div>
+		<div>
+		Sets the angles of this euler transform from a normalized quaternion based on the orientation specified by order.
+		</div>
+
+		<h3>[method:Euler reorder]( [page:String newOrder] ) [page:Euler this]</h3>
+		<div>
+		Resets the euler angle with a new order by creating a quaternion from this euler angle and then setting this euler angle with the quaternion and the new order. <br />
+		WARNING: this discards revolution information.
+		</div>
+
+		<h3>[method:Euler setFromVector3]([page:Vector3 vector], [page:String order]) [page:Euler this]</h3>
+		<div>
+		vector -- [page:Vector3].
+		order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
+		</div>
+		<div>
+		Optionally Vector3 to the XYZ parameters of Euler, and order to the Euler's order property.
+		</div>
+
+		<h3>[method:Vector3 toVector3]()</h3>
+		<div>
+		Returns the Euler's XYZ properties as a Vector3.
+		</div>
+
+		<h3>[method:Euler fromArray]([page:Array array]) [page:Euler this]</h3>
+		<div>
+		array -- [page:Array] of length 3 or 4. array[3] is an optional order argument.
+		</div>
+		<div>
+		Assigns this euler's x angle to array[0]. <br />
+		Assigns this euler's y angle to array[1]. <br />
+		Assigns this euler's z angle to array[2]. <br />
+		Optionally assigns this euler's order to array[3].
+		</div>
+
+		<h3>[method:Array toArray]( [page:Array array] )</h3>
+		<div>
+		array -- Optional array to store the euler.
+		</div>
+		<div>
+		Returns an array [x, y, z, order]
+		</div>
+
+		<h3>[method:Boolean equals]( [page:Euler euler] )</h3>
+		<div>
+		Checks for strict equality of this euler and *euler*.
+		</div>
+
+		<h3>[method:Euler clone]()</h3>
+		<div>
+		Returns a new euler created from this euler.
+		</div>
+
+
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
 </html>

+ 10 - 0
docs/api/math/Matrix4.html

@@ -71,6 +71,16 @@
 		Copies the translation component of the supplied matrix *m* into this matrix translation component.
 		</div>
 
+		<h3>[method:Matrix4 makeBasis]( [page:Vector3 xAxis], [page:Vector3 zAxis], [page:Vector3 zAxis] ) [page:Matrix4 this]</h3>
+		<div>
+		Creates the basis matrix consisting of the three provided axis vectors.  Returns the current matrix.
+		</div>
+
+		<h3>[method:Matrix4 extractBasis]( [page:Vector3 xAxis], [page:Vector3 zAxis], [page:Vector3 zAxis] ) [page:Matrix4 this]</h3>
+		<div>
+		Extracts basis of into the three axis vectors provided.  Returns the current matrix.
+		</div>
+
 		<h3>[method:Matrix4 extractRotation]( [page:Matrix4 m] ) [page:Matrix4 this]</h3>
 		<div>
 		Extracts the rotation of the supplied matrix *m* into this matrix rotation component.

+ 8 - 5
docs/api/math/Quaternion.html

@@ -131,15 +131,18 @@
 		<h3>[method:Quaternion slerp]([page:Quaternion qb], [page:float t])</h3>
 		<div>
 		qb -- Target quaternion rotation.<br />
-		t -- Normalized [0..1] interpolation factor. 
+		t -- Normalized [0..1] interpolation factor.
 		</div>
 		<div>
 		Handles the spherical linear interpolation between this quaternion's configuration
-		and that of *qb*. *t* represents how close to the current (0) or target (1) rotation the 
-		result should be. 
+		and that of *qb*. *t* represents how close to the current (0) or target (1) rotation the
+		result should be.
 		</div>
 
-		<h3>.toArray() [page: Array]</h3>
+		<h3>[method:Array toArray]( [page:Array array] )</h3>
+		<div>
+		array -- Array to store the quaternion.
+		</div>
 		<div>
 		Returns the numerical elements of this quaternion in an array of format (x, y, z, w).
 		</div>
@@ -155,7 +158,7 @@
 
 		<h3>[method:Float lengthSq]()</h3>
 		<div>
-		Calculates the squared length of the quaternion. 
+		Calculates the squared length of the quaternion.
 		</div>
 
 		<h3>[method:Quaternion fromArray]([page:Array array])</h3>

+ 14 - 1
docs/api/math/Vector2.html

@@ -181,6 +181,16 @@
 		Linear interpolation between this vector and v, where alpha is the percent along the line.
 		</div>
 
+		<h3>[method:Vector2 lerpVectors]([page:Vector2 v1], [page:Vector2 v2], [page:Float alpha]) [page:Vector2 this]</h3>
+		<div>
+		v1 -- [page:Vector2] <br />
+		v2 -- [page:Vector2] <br />
+		alpha -- [page:Float] between 0 and 1.
+		</div>
+		<div>
+		Sets this vector to be the vector linearly interpolated between *v1* and *v2* with *alpha* factor.
+		</div>
+
 		<h3>[method:undefined setComponent]([page:Integer index], [page:Float value])</h3>
 		<div>
 		index -- 0 or 1 <br />
@@ -216,7 +226,10 @@
 		Sets this vector's x value to be array[0] and y value to be array[1].
 		</div>
 
-		<h3>[method:Array toArray]()</h3>
+		<h3>[method:Array toArray]( [page:Array array] )</h3>
+		<div>
+		array -- Optional array to store the vector.
+		</div>
 		<div>
 		Returns an array [x, y].
 		</div>

+ 14 - 1
docs/api/math/Vector3.html

@@ -342,6 +342,16 @@
 		Linear Interpolation between this vector and vector v, where alpha is the percent along the line.
 		</div>
 
+		<h3>[method:Vector3 lerpVectors]([page:Vector3 v1], [page:Vector3 v2], [page:Float alpha]) [page:Vector3 this]</h3>
+		<div>
+		v1 -- [page:Vector3] <br />
+		v2 -- [page:Vector3] <br />
+		alpha -- [page:Float] between 0 and 1.
+		</div>
+		<div>
+		Sets this vector to be the vector linearly interpolated between *v1* and *v2* with *alpha* factor.
+		</div>
+
 		<h3>[method:Float angleTo]([page:Vector3 v])</h3>
 		<div>
 		v -- [page:Vector3]
@@ -391,7 +401,10 @@
 		Multiplies this vector and m, and divides by perspective.
 		</div>
 
-		<h3>[method:Array toArray]()</h3>
+		<h3>[method:Array toArray]( [page:Array array] )</h3>
+		<div>
+		array -- Optional array to store the vector.
+		</div>
 		<div>
 		Assigns this vector's x value to array[0]. <br />
 		Assigns this vector's y value to array[1]. <br />

+ 14 - 6
docs/api/math/Vector4.html

@@ -113,6 +113,11 @@
 		Linearly interpolate between this vector and *v* with *alpha* factor.
 		</div>
 
+		<h3>[method:Vector4 lerpVectors]( [page:Vector4 v1], [page:Vector4 v2], [page:Float alpha] ) [page:Vector4 this]</h3>
+		<div>
+		Sets this vector to be the vector linearly interpolated between *v1* and *v2* with *alpha* factor.
+		</div>
+
 		<h3>[method:Vector4 clone]()</h3>
 		<div>
 		Clones this vector.
@@ -181,7 +186,7 @@
 		v -- [page:Vector4]
 		</div>
 		<div>
-		If this vector's x, y, z, or w value is greater than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value. 
+		If this vector's x, y, z, or w value is greater than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector4 addScalar]([page:Float s]) [page:Vector4 this]</h3>
@@ -199,7 +204,7 @@
 		<div>
 		Checks to see if this vector matches vector v.
 		</div>
-		
+
 		<h3>[method:Vector4 setAxisAngleFromRotationMatrix]([page:Matrix4 m]) [page:Vector4 this]</h3>
 		<div>
 		m -- [page:Matrix4]
@@ -231,7 +236,7 @@
 		Index 1: y<br/>
 		Index 2: z<br/>
 		Index 3: w<br/>
- 
+
 		</div>
 
 		<h3>[method:null setComponent]([page:Integer index], [page:Float value])</h3>
@@ -241,13 +246,13 @@
 		</div>
 		<div>
 		Sets the value of the vector component	x, y, or z by an index.<br/><br/>
-		
+
 		Index 0: x<br/>
 		Index 1: y<br/>
 		Index 2: z<br/>
 		Index 3: w<br/>
 		</div>
-		
+
 		<h3>[method:Vector4 fromArray]([page:Array array]) [page:Vector4 this]</h3>
 		<div>
 		array -- [page:Array] An array formatted [x, y, z, w]
@@ -256,7 +261,10 @@
 		Sets the vector's components based on an array formatted like [x, y, z, w]
 		</div>
 
-		<h3>[method:Array toArray]()</h3>
+		<h3>[method:Array toArray]( [page:Array array] )</h3>
+		<div>
+		array -- Optional array to store the vector.
+		</div>
 		<div>
 		Returns an array in the format [x, y, z, w]
 		</div>

+ 5 - 0
docs/api/objects/Line.html

@@ -70,6 +70,11 @@
 
 		<h2>Methods</h2>
 
+		<h3>[method:Array raycast]([page:Raycaster raycaster], [page:Array intersects])</h3>
+		<div>
+		Get intersections between a casted ray and this Line. [page:Raycaster.intersectObject] will call this method.
+		</div>
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 6 - 0
docs/api/objects/Mesh.html

@@ -60,6 +60,12 @@
 		Updates the morphtargets to have no influence on the object.
 		</div>
 
+		<h3>[method:Array raycast]([page:Raycaster raycaster], [page:Array intersects])</h3>
+		<div>
+		Get intersections between a casted ray and this mesh. [page:Raycaster.intersectObject] will call this method.
+		</div>
+
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 5 - 0
docs/api/objects/PointCloud.html

@@ -42,6 +42,11 @@
 		This creates a clone of the particle system.
 		</div>
 
+		<h3>[method:Array raycast]([page:Raycaster raycaster], [page:Array intersects])</h3>
+		<div>
+		Get intersections between a casted ray and this PointCloud. [page:Raycaster.intersectObject] will call this method.
+		</div>
+
 
 		<h2>Source</h2>
 

+ 1 - 1
docs/api/renderers/WebGLRenderTarget.html

@@ -69,7 +69,7 @@
 
 		<h3>[property:number type]</h3>
 		<div>
-		The default is THREE.UnsignedByteType. Other valid types (as WebGL allows) are THREE.ByteType, THREE.ShortType, THREE.UnsignedShortType, THREE.IntType, THREE.UnsignedIntType, THREE.FloatType, THREE.UnsignedShort4444Type, THREE.UnsignedShort5551Type, and THREE.UnsignedShort565Type.
+		The default is THREE.UnsignedByteType. Other valid types (as WebGL allows) are THREE.ByteType, THREE.ShortType, THREE.UnsignedShortType, THREE.IntType, THREE.UnsignedIntType, THREE.HalfFloatType, THREE.FloatType, THREE.UnsignedShort4444Type, THREE.UnsignedShort5551Type, and THREE.UnsignedShort565Type.
 		</div>
 		
 		<h3>[property:boolean depthBuffer]</h3>

+ 2 - 2
docs/api/renderers/WebGLRenderer.html

@@ -184,8 +184,8 @@
 
 		<code>// Creates a renderer with red background
 		var renderer = new THREE.WebGLRenderer();
-		renderer.setSize(200, 100);
-		renderer.setClearColor(0xff0000, 1);
+		renderer.setSize( 200, 100 );
+		renderer.setClearColor( 0xff0000 );
 		</code>
 
 		<h3>[method:Color getClearColor]()</h3>

+ 1 - 1
docs/list.js

@@ -63,7 +63,6 @@ var list = {
 			[ "ObjectLoader", "api/loaders/ObjectLoader" ],
 			[ "PDBLoader", "api/loaders/PDBLoader" ],
 			[ "SVGLoader", "api/loaders/SVGLoader" ],
-			[ "SceneLoader", "api/loaders/SceneLoader" ],
 			[ "TextureLoader", "api/loaders/TextureLoader" ],
 			[ "TGALoader", "api/loaders/TGALoader" ],
 			[ "XHRLoader", "api/loaders/XHRLoader" ]
@@ -219,6 +218,7 @@ var list = {
 			[ "ArrowHelper", "api/extras/helpers/ArrowHelper" ],
 			[ "AxisHelper", "api/extras/helpers/AxisHelper" ],
 			[ "BoundingBoxHelper", "api/extras/helpers/BoundingBoxHelper" ],
+			[ "BoxHelper", "api/extras/helpers/BoxHelper" ],
 			[ "CameraHelper", "api/extras/helpers/CameraHelper" ],
 			[ "DirectionalLightHelper", "api/extras/helpers/DirectionalLightHelper" ],
 			[ "EdgesHelper", "api/extras/helpers/EdgesHelper" ],

+ 4 - 4
docs/manual/introduction/Creating-a-scene.html

@@ -9,13 +9,13 @@
 	<body>
 		<h1>[name]</h1>
 
-		<div>The goal of this section is to give a brief introduction to Three.js. We will start by setting up a scene, with a spinning cube. A working example is provided at the bottom of the page, if you get stuck, and need help.</div>
+		<div>The goal of this section is to give a brief introduction to Three.js. We will start by setting up a scene, with a spinning cube. A working example is provided at the bottom of the page in case you get stuck and need help.</div>
 
 		<h2>What is Three.js?</h2>
 
-		<div>If you're reading this, you probably have some understanding of what Three.js is, and what it helps you with, but let's try to describe it briefly anyway.</div>
+		<div>Let's try to describe it briefly:</div>
 
-		<div>Three.js is a library that makes WebGL - 3D in the browser - very easy. While a simple cube in raw WebGL would turn out hundreds of lines of Javascript and shader code, a Three.js equivalent is only a fraction of that.</div>
+		<div>Three.js is a library that makes WebGL - 3D in the browser - easy to use. While a simple cube in raw WebGL would turn out hundreds of lines of Javascript and shader code, a Three.js equivalent is only a fraction of that.</div>
 
 		<h2>Before we start</h2>
 		<div>Before you can use Three.js, you need somewhere to display it. Save the following HTML to a file on your computer, along with a copy of <a href="http://threejs.org/build/three.min.js">three.min.js</a> in the js/ directory, and open it in your browser.</div>
@@ -53,7 +53,7 @@
 		document.body.appendChild( renderer.domElement );
 		</code>
 
-		<div>Let's take a moment to explain what's going on here. We have now set up the scene, our camera and the renderer. There are a few different cameras in Three.js, but we'll go more into that later. For now, let's use a PerspectiveCamera. The first attribute is the <strong>field of view</strong>.</div>
+		<div>Let's take a moment to explain what's going on here. We have now set up the scene, our camera and the renderer. There are a few different cameras in Three.js. For now, let's use a PerspectiveCamera. The first attribute is the <strong>field of view</strong>.</div>
 
 		<div>The second one is the <strong>aspect ratio</strong>. You almost always want to use the width of the element divided by the height, or you'll get the same result as when you play old movies on a widescreen TV - the image looks squished.</div>
 

+ 119 - 123
docs/scenes/js/material.js

@@ -3,60 +3,60 @@
  */
 
 var constants = {
-	
+
 	combine: {
-		
+
 		"THREE.MultiplyOperation" : THREE.MultiplyOperation,
 		"THREE.MixOperation" : THREE.MixOperation,
 		"THREE.AddOperation" : THREE.AddOperation
-		
+
 	},
-	
+
 	side : {
-		
+
 		"THREE.FrontSide" : THREE.FrontSide,
 		"THREE.BackSide" : THREE.BackSide,
 		"THREE.DoubleSide" : THREE.DoubleSide
-		
+
 	},
-	
+
 	shading : {
-		
+
 		"THREE.NoShading" : THREE.NoShading,
 		"THREE.FlatShading" : THREE.FlatShading,
 		"THREE.SmoothShading" : THREE.SmoothShading
-		
+
 	},
 
 	colors : {
-		
+
 		"THREE.NoColors" : THREE.NoColors,
 		"THREE.FaceColors" : THREE.FaceColors,
 		"THREE.VertexColors" : THREE.VertexColors
-		
+
 	},
-	
+
 	blendingMode : {
-		
+
 		"THREE.NoBlending" : THREE.NoBlending,
 		"THREE.NormalBlending" : THREE.NormalBlending,
 		"THREE.AdditiveBlending" : THREE.AdditiveBlending,
 		"THREE.SubtractiveBlending" : THREE.SubtractiveBlending,
 		"THREE.MultiplyBlending" : THREE.MultiplyBlending,
 		"THREE.CustomBlending" : THREE.CustomBlending
-		
+
 	},
-	
+
 	equations : {
-		
+
 		"THREE.AddEquation" : THREE.AddEquation,
 		"THREE.SubtractEquation" : THREE.SubtractEquation,
 		"THREE.ReverseSubtractEquation" : THREE.ReverseSubtractEquation
-		
+
 	},
-	
+
 	destinationFactors : {
-		
+
 		"THREE.ZeroFactor" : THREE.ZeroFactor,
 		"THREE.OneFactor" : THREE.OneFactor,
 		"THREE.SrcColorFactor" : THREE.SrcColorFactor,
@@ -65,38 +65,38 @@ var constants = {
 		"THREE.OneMinusSrcAlphaFactor" : THREE.OneMinusSrcAlphaFactor,
 		"THREE.DstAlphaFactor" : THREE.DstAlphaFactor,
 		"THREE.OneMinusDstAlphaFactor" : THREE.OneMinusDstAlphaFactor
-		
+
 	},
-	
+
 	sourceFactors : {
-		
+
 		"THREE.DstColorFactor" : THREE.DstColorFactor,
 		"THREE.OneMinusDstColorFactor" : THREE.OneMinusDstColorFactor,
 		"THREE.SrcAlphaSaturateFactor" : THREE.SrcAlphaSaturateFactor
-		
+
 	}
-	
+
 }
 
 function getObjectsKeys( obj ) {
-	
+
 	var keys = [];
-	
+
 	for ( var key in obj ) {
-		
+
 		if ( obj.hasOwnProperty( key ) ) {
-			
+
 			keys.push( key );
-			
+
 		}
-		
+
 	}
-	
+
 	return keys;
 }
 
 var envMaps = (function () {
-	
+
 	var path = "../../examples/textures/cube/SwedishRoyalCastle/";
 	var format = '.jpg';
 	var urls = [
@@ -111,32 +111,32 @@ var envMaps = (function () {
 
 	var refractionCube = new THREE.Texture( reflectionCube.image, THREE.CubeRefractionMapping );
 	reflectionCube.format = THREE.RGBFormat;
-	
+
 	return {
 		none : null,
 		reflection : reflectionCube,
 		refraction : refractionCube
 	};
-	
+
 })();
 
 var envMapKeys = getObjectsKeys( envMaps );
 
 var textureMaps = (function () {
-	
+
 	return {
 		none : null,
 		grass : THREE.ImageUtils.loadTexture( "../../examples/textures/terrain/grasslight-thin.jpg" )
 	};
-	
+
 })();
 
 var textureMapKeys = getObjectsKeys( textureMaps );
 
 function generateVertexColors ( geometry ) {
-	
+
 	for ( var i=0, il = geometry.faces.length; i < il; i++ ) {
-				
+
 		geometry.faces[i].vertexColors.push( new THREE.Color().setHSL(
 			i / il * Math.random(),
 			0.5,
@@ -152,15 +152,15 @@ function generateVertexColors ( geometry ) {
 			0.5,
 			0.5
 		) );
-		
+
 		geometry.faces[i].color = new THREE.Color().setHSL(
 			i / il * Math.random(),
 			0.5,
 			0.5
 		);
-		
+
 	}
-	
+
 }
 
 function generateMorphTargets ( mesh, geometry ) {
@@ -172,7 +172,7 @@ function generateMorphTargets ( mesh, geometry ) {
 		vertices.push( geometry.vertices[ i ].clone() );
 
 		scale = 1 + Math.random() * 0.3;
-		
+
 		vertices[ vertices.length - 1 ].x *= scale;
 		vertices[ vertices.length - 1 ].y *= scale;
 		vertices[ vertices.length - 1 ].z *= scale;
@@ -180,31 +180,31 @@ function generateMorphTargets ( mesh, geometry ) {
 	}
 
 	geometry.morphTargets.push( { name: "target1", vertices: vertices } );
-	
+
 	geometry.update
 
 }
 
 function handleColorChange ( color ) {
-	
+
 	return function ( value ){
-		
+
 		if (typeof value === "string") {
-			
+
 			value = value.replace('#', '0x');
-			
+
 		}
-		
+
 		color.setHex( value );
-		
+
     };
-	
+
 }
 
 function needsUpdate ( material, geometry ) {
-	
+
 	return function () {
-		
+
 		material.shading = +material.shading; //Ensure number
 		material.vertexColors = +material.vertexColors; //Ensure number
 		material.side = +material.side; //Ensure number
@@ -212,63 +212,63 @@ function needsUpdate ( material, geometry ) {
 		geometry.verticesNeedUpdate = true;
 		geometry.normalsNeedUpdate = true;
 		geometry.colorsNeedUpdate = true;
-		
+
 	};
-	
+
 };
 
 function updateMorphs ( torus, material ) {
 
 	return function () {
-		
+
 		torus.updateMorphTargets();
 		material.needsUpdate = true;
-		
+
 	};
-	
+
 }
 
 function updateTexture ( material, materialKey, textures ) {
 
 	return function ( key ) {
-		
+
 		material[materialKey] = textures[key];
 		material.needsUpdate = true;
-		
+
 	};
-	
+
 }
 
 function guiScene ( gui, scene ) {
-	
+
 	var folder = gui.addFolder('Scene');
-	
+
 	var data = {
 		background : "#000000",
 		"ambient light" : ambientLight.color.getHex()
 	}
-	
+
 	var color = new THREE.Color();
 	var colorConvert = handleColorChange( color );
-	
+
 	folder.addColor( data, "background" ).onChange( function ( value ) {
-		
+
 		colorConvert( value );
-		
-		renderer.setClearColor(color.getHex(), 1);
-		
+
+		renderer.setClearColor( color.getHex() );
+
 	} );
-	
+
 	folder.addColor( data, "ambient light" ).onChange( handleColorChange( ambientLight.color ) )
-	
+
 	guiSceneFog( folder, scene );
-	
+
 }
 
 function guiSceneFog ( folder, scene ) {
-	
+
 	var fogFolder = folder.addFolder('scene.fog');
-	
+
 	var fog = new THREE.Fog( 0x3f7b9d, 0, 60 );
 
 	var data = {
@@ -277,29 +277,29 @@ function guiSceneFog ( folder, scene ) {
 			"scene.fog.color" : fog.color.getHex()
 		}
 	};
-	
+
 	fogFolder.add( data.fog, 'THREE.Fog()' ).onChange( function ( useFog ) {
-		
+
 		if ( useFog ) {
-			
+
 			scene.fog = fog;
-			
+
 		} else {
-			
+
 			scene.fog = null;
-			
+
 		}
-		
+
 	} );
-	
+
 	fogFolder.addColor( data.fog, 'scene.fog.color').onChange( handleColorChange( fog.color ) );
-	
+
 }
 
 function guiMaterial ( gui, mesh, material, geometry ) {
-	
+
 	var folder = gui.addFolder('THREE.Material');
-	
+
 	folder.add( material, 'transparent' );
 	folder.add( material, 'opacity', 0, 1 );
 	// folder.add( material, 'blending', constants.blendingMode );
@@ -315,11 +315,11 @@ function guiMaterial ( gui, mesh, material, geometry ) {
 	// folder.add( material, 'overdraw', 0, 5 );
 	folder.add( material, 'visible' );
 	folder.add( material, 'side', constants.side ).onChange( needsUpdate( material, geometry ) );
-	
+
 }
 
 function guiMeshBasicMaterial ( gui, mesh, material, geometry ) {
-	
+
 	var data = {
 		color : material.color.getHex(),
 		envMaps : envMapKeys,
@@ -328,7 +328,7 @@ function guiMeshBasicMaterial ( gui, mesh, material, geometry ) {
 		specularMap : textureMapKeys,
 		alphaMap : textureMapKeys
 	};
-		
+
 	var folder = gui.addFolder('THREE.MeshBasicMaterial');
 
 	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
@@ -337,7 +337,7 @@ function guiMeshBasicMaterial ( gui, mesh, material, geometry ) {
 	folder.add( material, 'shading', constants.shading);
 	folder.add( material, 'vertexColors', constants.colors).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'fog' );
-	
+
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
 	folder.add( data, 'map', textureMapKeys ).onChange( updateTexture( material, 'map', textureMaps ) );
 	folder.add( data, 'lightMap', textureMapKeys ).onChange( updateTexture( material, 'lightMap', textureMaps ) );
@@ -348,36 +348,36 @@ function guiMeshBasicMaterial ( gui, mesh, material, geometry ) {
 	folder.add( material, 'reflectivity', 0, 1 );
 	folder.add( material, 'refractionRatio', 0, 1 );
 	//folder.add( material, 'skinning' );
-	
+
 }
 
 function guiMeshDepthMaterial ( gui, mesh, material, geometry ) {
-	
+
 	var folder = gui.addFolder('THREE.MeshDepthMaterial');
-		
+
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'morphTargets' ).onChange( updateMorphs( mesh, material ) );
-	
+
 }
 
 function guiMeshNormalMaterial ( gui, mesh, material, geometry ) {
-	
+
 	var folder = gui.addFolder('THREE.MeshNormalMaterial');
-	
+
 	folder.add( material, 'shading', constants.shading).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'morphTargets' ).onChange( updateMorphs( mesh, material ) );
-	
+
 }
 
 function guiLineBasicMaterial ( gui, mesh, material, geometry ) {
-	
+
 	var data = {
 		color : material.color.getHex()
 	};
-		
+
 	var folder = gui.addFolder('THREE.LineBasicMaterial');
 
 	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
@@ -386,14 +386,13 @@ function guiLineBasicMaterial ( gui, mesh, material, geometry ) {
 	folder.add( material, 'linejoin', ["round", "bevel", "miter"] );
 	folder.add( material, 'vertexColors', constants.colors).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'fog' );
-	
+
 }
 
 function guiMeshLambertMaterial ( gui, mesh, material, geometry ) {
-	
+
 	var data = {
 		color : material.color.getHex(),
-		ambient : material.ambient.getHex(),
 		emissive : material.emissive.getHex(),
 		envMaps : envMapKeys,
 		map : textureMapKeys,
@@ -401,15 +400,14 @@ function guiMeshLambertMaterial ( gui, mesh, material, geometry ) {
 		specularMap : textureMapKeys,
 		alphaMap : textureMapKeys
 	};
-	
+
 	var envObj = {};
-			
+
 	var folder = gui.addFolder('THREE.MeshLambertMaterial');
 
 	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
-	folder.addColor( data, 'ambient' ).onChange( handleColorChange( material.ambient ) );
 	folder.addColor( data, 'emissive' ).onChange( handleColorChange( material.emissive ) );
-	
+
 	folder.add( material, 'shading', constants.shading ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
@@ -426,14 +424,13 @@ function guiMeshLambertMaterial ( gui, mesh, material, geometry ) {
 	folder.add( material, 'reflectivity', 0, 1 );
 	folder.add( material, 'refractionRatio', 0, 1 );
 	//folder.add( material, 'skinning' );
-	
+
 }
 
 function guiMeshPhongMaterial ( gui, mesh, material, geometry ) {
-	
+
 	var data = {
 		color : material.color.getHex(),
-		ambient : material.ambient.getHex(),
 		emissive : material.emissive.getHex(),
 		specular : material.specular.getHex(),
 		envMaps : envMapKeys,
@@ -442,15 +439,14 @@ function guiMeshPhongMaterial ( gui, mesh, material, geometry ) {
 		specularMap : textureMapKeys,
 		alphaMap : textureMapKeys
 	};
-		
+
 	var folder = gui.addFolder('THREE.MeshPhongMaterial');
 
 	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
-	folder.addColor( data, 'ambient' ).onChange( handleColorChange( material.ambient ) );
 	folder.addColor( data, 'emissive' ).onChange( handleColorChange( material.emissive ) );
 	folder.addColor( data, 'specular' ).onChange( handleColorChange( material.specular ) );
 
-	folder.add( material, 'shininess', 0, 100);
+	folder.add( material, 'shininess', 1, 100);
 	folder.add( material, 'shading', constants.shading).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
@@ -461,16 +457,16 @@ function guiMeshPhongMaterial ( gui, mesh, material, geometry ) {
 	folder.add( data, 'lightMap', textureMapKeys ).onChange( updateTexture( material, 'lightMap', textureMaps ) );
 	folder.add( data, 'specularMap', textureMapKeys ).onChange( updateTexture( material, 'specularMap', textureMaps ) );
 	folder.add( data, 'alphaMap', textureMapKeys ).onChange( updateTexture( material, 'alphaMap', textureMaps ) );
-	
+
 }
 
 function chooseFromHash ( gui, mesh, geometry ) {
 
 	var selectedMaterial = window.location.hash.substring(1) || "MeshBasicMaterial";
 	var material;
-	
+
 	switch (selectedMaterial) {
-		
+
 	case "MeshBasicMaterial" :
 
 		material = new THREE.MeshBasicMaterial({color: 0x2194CE});
@@ -480,7 +476,7 @@ function chooseFromHash ( gui, mesh, geometry ) {
 		return material;
 
 		break;
-	
+
 	case "MeshLambertMaterial" :
 
 		material = new THREE.MeshLambertMaterial({color: 0x2194CE});
@@ -490,7 +486,7 @@ function chooseFromHash ( gui, mesh, geometry ) {
 		return material;
 
 		break;
-	
+
 	case "MeshPhongMaterial" :
 
 		material = new THREE.MeshPhongMaterial({color: 0x2194CE});
@@ -500,27 +496,27 @@ function chooseFromHash ( gui, mesh, geometry ) {
 		return material;
 
 		break;
-	
+
 	case "MeshDepthMaterial" :
-		
+
 		material = new THREE.MeshDepthMaterial({color: 0x2194CE});
 		guiMaterial( gui, mesh, material, geometry );
 		guiMeshDepthMaterial( gui, mesh, material, geometry );
 
 		return material;
-		
+
 		break;
-	
+
 	case "MeshNormalMaterial" :
-		
+
 		material = new THREE.MeshNormalMaterial();
 		guiMaterial( gui, mesh, material, geometry );
 		guiMeshNormalMaterial( gui, mesh, material, geometry );
 
 		return material;
-		
+
 		break;
-		
+
 	case "LineBasicMaterial" :
 
 		material = new THREE.LineBasicMaterial({color: 0x2194CE});
@@ -531,5 +527,5 @@ function chooseFromHash ( gui, mesh, geometry ) {
 
 		break;
 	}
-	
+
 }

+ 41 - 17
editor/css/dark.css

@@ -1,23 +1,34 @@
-.FancySelect {
+.Outliner {
+	color: #868686;
 	background: #222;
-	border: 1px solid #3C3C3C;
 	padding: 0;
+	width: 100%;
+	height: 140px;
+	font-size: 12px;
 	cursor: default;
 	overflow: auto;
 	outline: none;
 }
 
-	.FancySelect .option {
+	.Outliner .option {
 		padding: 4px;
 		white-space: nowrap;
 	}
 
-	.FancySelect .option.active {
+	.Outliner .option.active {
 		background-color: #153C5E;
 	}
 
+.Panel.Collapsible.collapsed .Static .Button {
+	border-left-color: #444;
+}
+
+.Panel.Collapsible:not(.collapsed) .Static .Button {
+	border-top-color: #444;
+}
+
 input.Number {
-	color: #2A75B7;
+	color: #2A75B7!important;
 	font-size: 12px;							/** TODO: Use of !imporant is not ideal **/
 	background-color: transparent!important;	/* For now this is a quick fix a rendering issue due to inherited background */
 	border: 1px solid transparent;
@@ -37,6 +48,15 @@ input.Number {
 		text-shadow: 1px 1px 0px rgba(0,0,0,0.25);
 	}
 
+#script {
+	position: absolute;
+	top: 32px;
+	left: 0px;
+	right: 300px;
+	bottom: 32px;
+	opacity: 0.9;
+}
+
 #player {
 	position: absolute;
 	top: 32px;
@@ -52,6 +72,8 @@ input.Number {
 	background: #111;
 	padding: 0px;
 	margin: 0px;
+	right: 0px;
+	top: 0px;
 }
 
 	#menubar .menu {
@@ -78,7 +100,7 @@ input.Number {
 			display: none;
 			padding: 5px 0px;
 			background: #111;
-			width: 140px;
+			width: 150px;
 		}
 
 		#menubar .menu:hover .options {
@@ -86,11 +108,11 @@ input.Number {
 		}
 
 			#menubar .menu .options hr {
-				border-color: #444;
+				border-color: #333;
 			}
 
 			#menubar .menu .options .option {
-				color: #666;
+				color: #888;
 				background-color: transparent;
 				padding: 5px 10px;
 				margin: 0px !important;
@@ -102,7 +124,6 @@ input.Number {
 				}
 
 				#menubar .menu .options .option:active {
-					color: #666;
 					background: transparent;
 				}
 
@@ -116,10 +137,16 @@ input.Number {
 	overflow: auto;
 }
 
+	#sidebar * {
+		vertical-align: middle;
+	}
+
 	#sidebar input,
 	#sidebar textarea,
 	#sidebar select {
-		background: #ccc;
+		background: #222;
+		border: 1px solid transparent;
+		color: #888;
 	}
 
 	#sidebar .Panel {
@@ -136,13 +163,6 @@ input.Number {
 		border-top: 1px solid #333;
 	}
 
-	#sidebar #outliner {
-		width: 100%;
-		height: 140px;
-		color: #868686;
-		font-size: 12px;
-	}
-
 	#sidebar .Panel.Material canvas {
 
 		border: solid 1px #5A5A5A;
@@ -159,6 +179,10 @@ input.Number {
 	color: #333;
 }
 
+	#toolbar * {
+		vertical-align: middle;
+	}
+
 	#toolbar .Panel {
 		padding: 4px;
 		color: #888;

+ 30 - 14
editor/css/light.css

@@ -1,24 +1,27 @@
-.FancySelect {
+.Outliner {
+	color: #444;
 	background: #fff;
-	border: 1px solid #ccc;
 	padding: 0;
+	width: 100%;
+	height: 140px;
+	font-size: 12px;
 	cursor: default;
 	overflow: auto;
 	outline: none;
 }
 
-	.FancySelect .option {
+	.Outliner .option {
 		padding: 4px;
 		color: #666;
 		white-space: nowrap;
 	}
 
-	.FancySelect .option.active {
+	.Outliner .option.active {
 		background-color: #f8f8f8;
 	}
 
 input.Number {
-	color: #0080f0;
+	color: #0080f0!important;
 	font-size: 12px;							/** TODO: Use of !imporant is not ideal **/
 	background-color: transparent!important;	/* For now this is a quick fix a rendering issue due to inherited background */
 	border: 1px solid transparent;
@@ -38,6 +41,15 @@ input.Number {
 		text-shadow: 1px 1px 0px rgba(0,0,0,0.25);
 	}
 
+#script {
+	position: absolute;
+	top: 32px;
+	left: 0px;
+	right: 300px;
+	bottom: 32px;
+	opacity: 0.9;
+}
+
 #player {
 	position: absolute;
 	top: 32px;
@@ -53,6 +65,8 @@ input.Number {
 	background: #eee;
 	padding: 0px;
 	margin: 0px;
+	right: 0px;
+	top: 0px;
 }
 
 	#menubar .menu {
@@ -79,7 +93,7 @@ input.Number {
 			display: none;
 			padding: 5px 0px;
 			background: #eee;
-			width: 140px;
+			width: 150px;
 		}
 
 		#menubar .menu:hover .options {
@@ -117,10 +131,15 @@ input.Number {
 	overflow: auto;
 }
 
+	#sidebar * {
+		vertical-align: middle;
+	}
+
 	#sidebar input,
 	#sidebar textarea,
 	#sidebar select {
-		/* background: #ccc; */
+		border: 1px solid transparent;
+		color: #444;
 	}
 
 	#sidebar .Panel {
@@ -137,13 +156,6 @@ input.Number {
 		border-top: 1px solid #ccc;
 	}
 
-	#sidebar #outliner {
-		width: 100%;
-		height: 140px;
-		color: #444;
-		font-size: 12px;
-	}
-
 #toolbar {
 	position: absolute;
 	left: 0px;
@@ -154,6 +166,10 @@ input.Number {
 	color: #333;
 }
 
+	#toolbar * {
+		vertical-align: middle;
+	}
+
 	#toolbar .Panel {
 		padding: 4px;
 		color: #888;

+ 12 - 6
editor/css/main.css

@@ -1,7 +1,3 @@
-* {
-	vertical-align: middle;
-}
-
 body {
 	font-family: Helvetica, Arial, sans-serif;
 	font-size: 14px;
@@ -19,6 +15,7 @@ button {
 }
 
 textarea {
+	tab-size: 4;
 	white-space: pre;
 	word-wrap: normal;
 }
@@ -70,6 +67,15 @@ textarea, input { outline: none; } /* osx */
 		display: none;
 	}
 
+.CodeMirror {
+
+	position: absolute !important;
+	top: 37px;
+	width: 100% !important;
+	height: calc(100% - 37px) !important;
+
+}
+
 /* scene types */
 
 .type {
@@ -110,7 +116,7 @@ textarea, input { outline: none; } /* osx */
 	color: #bbeebb;
 }
 .TorusGeometry {
-	color: #aaeeaa;	
+	color: #aaeeaa;
 }
 
 /* */
@@ -121,4 +127,4 @@ textarea, input { outline: none; } /* osx */
 
 .MeshPhongMaterial {
 	color: #ffaa88;
-}
+}

+ 168 - 0
editor/examples/arkanoid.app.json

@@ -0,0 +1,168 @@
+{
+	"camera": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"object": {
+			"uuid": "8EFB9C06-6312-4975-B04A-C9E4549BE348",
+			"type": "PerspectiveCamera",
+			"name": "Camera",
+			"fov": 50,
+			"aspect": 1.536388140161725,
+			"near": 0.1,
+			"far": 100000,
+			"matrix": [0.9392361044883728,-1.2050817232989175e-8,-0.34327182173728943,0,-0.15080472826957703,0.8983326554298401,-0.41262128949165344,0,0.30837228894233704,0.4393158257007599,0.8437464833259583,0,142.32125854492188,202.75485229492188,389.40936279296875,1]
+		}
+	},
+	"scene": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"geometries": [
+			{
+				"uuid": "8F05A1F2-3877-478B-8DFC-F572AC61AB3A",
+				"type": "PlaneGeometry",
+				"width": 300,
+				"height": 400,
+				"widthSegments": 1,
+				"heightSegments": 1
+			},
+			{
+				"uuid": "7149652B-DBD7-4CB7-A600-27A9AC005C95",
+				"type": "BoxGeometry",
+				"width": 20,
+				"height": 10,
+				"depth": 10,
+				"widthSegments": 1,
+				"heightSegments": 1,
+				"depthSegments": 1
+			},
+			{
+				"uuid": "CABCC711-1331-4D4C-9FF6-409299F10C68",
+				"type": "SphereGeometry",
+				"radius": 5,
+				"widthSegments": 32,
+				"heightSegments": 16,
+				"phiStart": 0,
+				"phiLength": 6.28,
+				"thetaStart": 0,
+				"thetaLength": 3.14
+			},
+			{
+				"uuid": "A1D8B049-74DD-4B08-B5BC-8DCEC9AF0222",
+				"type": "BoxGeometry",
+				"width": 40,
+				"height": 10,
+				"depth": 10,
+				"widthSegments": 1,
+				"heightSegments": 1,
+				"depthSegments": 1
+			}],
+		"materials": [
+			{
+				"uuid": "2F69AF3A-DDF5-4BBA-87B5-80159F90DDBF",
+				"type": "MeshPhongMaterial",
+				"color": 86015,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "CFBEAD4C-6695-4A99-887B-8161E2947225",
+				"type": "MeshPhongMaterial",
+				"color": 16777215,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "043B208C-1F83-42C6-802C-E0E35621C27C",
+				"type": "MeshPhongMaterial",
+				"color": 16777215,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "40EC9BDA-91C0-4671-937A-2BCB6DA7EEBB",
+				"type": "MeshPhongMaterial",
+				"color": 13486790,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			}],
+		"object": {
+			"uuid": "31517222-A9A7-4EAF-B5F6-60751C0BABA3",
+			"type": "Scene",
+			"name": "Scene",
+			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
+			"children": [
+				{
+					"uuid": "EBBB1E63-6318-4752-AE2E-440A4E0B3EF3",
+					"type": "Mesh",
+					"name": "Ground",
+					"geometry": "8F05A1F2-3877-478B-8DFC-F572AC61AB3A",
+					"material": "2F69AF3A-DDF5-4BBA-87B5-80159F90DDBF",
+					"matrix": [1,0,0,0,0,0.000796250649727881,-0.9999997019767761,0,0,0.9999997019767761,0.000796250649727881,0,0,0,0,1]
+				},
+				{
+					"uuid": "6EE2E764-43E0-48E0-85F2-E0C8823C20DC",
+					"type": "DirectionalLight",
+					"name": "DirectionalLight 1",
+					"color": 16777215,
+					"intensity": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,100,200,150,1]
+				},
+				{
+					"uuid": "38219749-1E67-45F2-AB15-E64BA0940CAD",
+					"type": "Mesh",
+					"name": "Brick",
+					"geometry": "7149652B-DBD7-4CB7-A600-27A9AC005C95",
+					"material": "CFBEAD4C-6695-4A99-887B-8161E2947225",
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,5,0,1]
+				},
+				{
+					"uuid": "18FFA67C-F893-4E7A-8A76-8D996DEBE0C6",
+					"type": "Mesh",
+					"name": "Ball",
+					"geometry": "CABCC711-1331-4D4C-9FF6-409299F10C68",
+					"material": "043B208C-1F83-42C6-802C-E0E35621C27C",
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,5,35.54999923706055,1]
+				},
+				{
+					"uuid": "6D660D49-39B8-40C3-95F6-E4E007AA8D79",
+					"type": "Mesh",
+					"name": "Paddle",
+					"geometry": "A1D8B049-74DD-4B08-B5BC-8DCEC9AF0222",
+					"material": "40EC9BDA-91C0-4671-937A-2BCB6DA7EEBB",
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,5,159.54217529296875,1]
+				},
+				{
+					"uuid": "B0BEAF69-8B5D-4D87-ADCA-FDE83A02762D",
+					"type": "PointLight",
+					"name": "PointLight 2",
+					"color": 16777215,
+					"intensity": 1,
+					"distance": 0,
+					"decay": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-116.54356384277344,69.48957061767578,-206.8248291015625,1]
+				}]
+		}
+	},
+	"scripts": {
+		"6D660D49-39B8-40C3-95F6-E4E007AA8D79": [
+			{
+				"name": "User",
+				"source": "function mousemove( event ) {\n\n\tthis.position.x = ( event.clientX / player.width ) * 300 - 150;\n\n}\n\n// function update( event ) {}"
+			}],
+		"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}"
+			}]
+	}
+}

+ 168 - 0
editor/examples/camera.app.json

@@ -0,0 +1,168 @@
+{
+	"camera": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"object": {
+			"uuid": "F0D8434F-4603-415B-8024-792FE97B9600",
+			"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]
+		}
+	},
+	"scene": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"geometries": [
+			{
+				"uuid": "D8E200D3-27BC-49F8-A5C5-7384206E70FE",
+				"type": "BoxGeometry",
+				"width": 100,
+				"height": 100,
+				"depth": 100,
+				"widthSegments": 1,
+				"heightSegments": 1,
+				"depthSegments": 1
+			},
+			{
+				"uuid": "25BA32DB-8B02-4ABA-A77C-69868C464A1A",
+				"type": "CylinderGeometry",
+				"radiusTop": 0,
+				"radiusBottom": 40,
+				"height": 75,
+				"radialSegments": 4,
+				"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",
+				"radius": 40,
+				"detail": 2
+			}],
+		"materials": [
+			{
+				"uuid": "B5943856-E404-45D9-A427-4774202C2CD0",
+				"type": "MeshPhongMaterial",
+				"color": 37119,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "3F872310-2067-4BE4-9250-5B3F4E43797E",
+				"type": "MeshPhongMaterial",
+				"color": 15859456,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "4AE8130E-B6A8-47BC-ACCF-060973C74044",
+				"type": "MeshPhongMaterial",
+				"color": 16777215,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "E1826901-7922-4584-A25D-6D487E2C9BBD",
+				"type": "MeshPhongMaterial",
+				"color": 16711680,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			}],
+		"object": {
+			"uuid": "3741222A-BD8F-401C-A5D2-5A907E891896",
+			"type": "Scene",
+			"name": "Scene",
+			"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": "26DAAD69-725D-43B7-AF9D-990A99DEF8C5",
+					"type": "Mesh",
+					"name": "Box 1",
+					"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]
+				},
+				{
+					"uuid": "AAAFF2D6-4725-4AFC-A9FE-26419B11011F",
+					"type": "Mesh",
+					"name": "Cylinder 3",
+					"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",
+					"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]
+				},
+				{
+					"uuid": "E2939A7B-5E40-438A-8C1B-32126FBC6892",
+					"type": "PointLight",
+					"name": "PointLight 1",
+					"color": 9474221,
+					"intensity": 0.75,
+					"distance": 0,
+					"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]
+				}]
+		}
+	},
+	"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}"
+			}]
+	}
+}

+ 97 - 0
editor/examples/particles.app.json

@@ -0,0 +1,97 @@
+{
+	"camera": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"object": {
+			"uuid": "D722B468-8D40-4CAB-82D6-944D2D5A8D35",
+			"type": "PerspectiveCamera",
+			"name": "Camera",
+			"fov": 50,
+			"aspect": 1.2237762237762237,
+			"near": 0.1,
+			"far": 100000,
+			"matrix": [0.7071067690849304,-2.468905080377226e-9,-0.7071068286895752,0,-0.2357022613286972,0.9428090453147888,-0.235702246427536,0,0.6666666865348816,0.3333333134651184,0.6666666269302368,0,500,250,500,1]
+		}
+	},
+	"scene": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"geometries": [
+			{
+				"uuid": "5009F17C-E9D3-4D0E-82A6-2E23159128FB",
+				"type": "PlaneGeometry",
+				"width": 600,
+				"height": 600,
+				"widthSegments": 1,
+				"heightSegments": 1
+			},
+			{
+				"uuid": "8693E7B2-0009-4C4C-94C5-8E031557AEC2",
+				"type": "BoxGeometry",
+				"width": 4,
+				"height": 4,
+				"depth": 4,
+				"widthSegments": 1,
+				"heightSegments": 1,
+				"depthSegments": 1
+			}],
+		"materials": [
+			{
+				"uuid": "6EDB0369-7E11-4B0F-BF98-4BD761846D65",
+				"type": "MeshPhongMaterial",
+				"color": 16777215,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "F5361474-F5F1-412F-8D99-3699B868092D",
+				"type": "SpriteMaterial",
+				"color": 16777215
+			}],
+		"object": {
+			"uuid": "3741222A-BD8F-401C-A5D2-5A907E891896",
+			"type": "Scene",
+			"name": "Scene",
+			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
+			"children": [
+				{
+					"uuid": "05B57416-1BE5-4A96-BB05-9D9CD112D52B",
+					"type": "Mesh",
+					"name": "Ground",
+					"geometry": "5009F17C-E9D3-4D0E-82A6-2E23159128FB",
+					"material": "6EDB0369-7E11-4B0F-BF98-4BD761846D65",
+					"matrix": [1,0,0,0,0,0.0007962886593304574,-0.9999997019767761,0,0,0.9999997019767761,0.0007962886593304574,0,0,-2,0,1]
+				},
+				{
+					"uuid": "0A3CB873-07E6-4EEB-830B-68192504111B",
+					"type": "Sprite",
+					"name": "Particle",
+					"material": "F5361474-F5F1-412F-8D99-3699B868092D",
+					"matrix": [3,0,0,0,0,3,0,0,0,0,1,0,0,0,0,1]
+				},
+				{
+					"uuid": "40E5CDA4-0E39-4265-9293-3E9EC3207F61",
+					"type": "PointLight",
+					"name": "PointLight",
+					"color": 16777215,
+					"intensity": 10,
+					"distance": 0,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
+				}]
+		}
+	},
+	"scripts": {
+		"3741222A-BD8F-401C-A5D2-5A907E891896": [
+			{
+				"name": "Particle Fountain",
+				"source": "var original = this.getObjectByName( 'Particle' );\n\nvar particles = [];\n\nfunction update( event ) {\n\n\tif ( particles.length < 200 ) {\n\n\t\tvar velocity = new THREE.Vector3();\n\t\tvelocity.x = Math.random() * 10 - 5;\n\t\tvelocity.y = Math.random() * 10 + 10;\n\t\tvelocity.z = Math.random() * 10 - 5;\n\n\t\tvar particle = original.clone();\n\t\tparticle.userData.velocity = velocity;\n\t\tparticles.push( particle );\n\n\t\tthis.add( particle );\n\n\t}\n\n\tfor ( var i = 0; i < particles.length; i ++ ) {\n\n\t\tvar particle = particles[ i ];\n\n\t\tvar velocity = particle.userData.velocity;\n\n\t\tvelocity.y -= 0.98;\n\n\t\tparticle.position.add( velocity );\n\n\t\tif ( particle.position.y < 0 ) {\n\n\t\t\tparticle.position.y = 0;\n\n\t\t\tvelocity.y = - velocity.y;\n\t\t\tvelocity.multiplyScalar( 0.6 );\n\n\t\t}\n\n\t}\n\n}"
+			}]
+	}
+}

+ 134 - 0
editor/examples/pong.app.json

@@ -0,0 +1,134 @@
+{
+	"camera": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"object": {
+			"uuid": "8EFB9C06-6312-4975-B04A-C9E4549BE348",
+			"type": "PerspectiveCamera",
+			"name": "Camera",
+			"fov": 50,
+			"aspect": 1.3291139240506329,
+			"near": 0.1,
+			"far": 100000,
+			"matrix": [0.9522120356559753,4.209433246415983e-9,-0.3054378032684326,0,-0.17742955684661865,0.8139731884002686,-0.553142249584198,0,0.24861818552017212,0.5809023976325989,0.7750750780105591,0,186.46363830566406,435.67681884765625,581.3063354492188,1]
+		}
+	},
+	"scene": {
+		"metadata": {
+			"version": 4.3,
+			"type": "Object",
+			"generator": "ObjectExporter"
+		},
+		"geometries": [
+			{
+				"uuid": "77B20ED1-2871-4B14-A652-8F823B2A817E",
+				"type": "PlaneGeometry",
+				"width": 600,
+				"height": 400,
+				"widthSegments": 1,
+				"heightSegments": 1
+			},
+			{
+				"uuid": "7ADE0D01-A56A-4D33-869A-6C360E096EF7",
+				"type": "BoxGeometry",
+				"width": 10,
+				"height": 10,
+				"depth": 10,
+				"widthSegments": 1,
+				"heightSegments": 1,
+				"depthSegments": 1
+			},
+			{
+				"uuid": "E8C064B6-3454-4739-9E02-3B07B8E70B4C",
+				"type": "BoxGeometry",
+				"width": 20,
+				"height": 20,
+				"depth": 100,
+				"widthSegments": 1,
+				"heightSegments": 1,
+				"depthSegments": 1
+			}],
+		"materials": [
+			{
+				"uuid": "7EDF7C08-6325-418A-BBAB-89341C694730",
+				"type": "MeshPhongMaterial",
+				"color": 16777215,
+				"emissive": 0,
+				"specular": 16777215,
+				"shininess": 30
+			},
+			{
+				"uuid": "B1CAF098-FE36-45E1-BEBE-8D6AC04821CC",
+				"type": "MeshPhongMaterial",
+				"color": 16711680,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			},
+			{
+				"uuid": "FBDBE66D-B613-4741-802D-5AE1DE07DE46",
+				"type": "MeshPhongMaterial",
+				"color": 2752767,
+				"emissive": 0,
+				"specular": 1118481,
+				"shininess": 30
+			}],
+		"object": {
+			"uuid": "31517222-A9A7-4EAF-B5F6-60751C0BABA3",
+			"type": "Scene",
+			"name": "Scene",
+			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
+			"children": [
+				{
+					"uuid": "B47D0BFC-D63A-4CBB-985E-9C4DBDF086E4",
+					"type": "Mesh",
+					"name": "Ground",
+					"geometry": "77B20ED1-2871-4B14-A652-8F823B2A817E",
+					"material": "7EDF7C08-6325-418A-BBAB-89341C694730",
+					"matrix": [1,0,0,0,0,0.0007960614748299122,-0.9999997019767761,0,0,0.9999997019767761,0.0007960614748299122,0,0,-10,0,1]
+				},
+				{
+					"uuid": "CE13E58A-4E8B-4F72-9E2E-7DE57C58F989",
+					"type": "Mesh",
+					"name": "Ball",
+					"geometry": "7ADE0D01-A56A-4D33-869A-6C360E096EF7",
+					"material": "B1CAF098-FE36-45E1-BEBE-8D6AC04821CC",
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
+				},
+				{
+					"uuid": "2AAEA3AA-EC45-492B-B450-10473D1EC6C5",
+					"type": "Mesh",
+					"name": "Pad 1",
+					"geometry": "E8C064B6-3454-4739-9E02-3B07B8E70B4C",
+					"material": "FBDBE66D-B613-4741-802D-5AE1DE07DE46",
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-240,0,0,1]
+				},
+				{
+					"uuid": "F1DD46A7-6584-4A37-BC76-852C3911077E",
+					"type": "Mesh",
+					"name": "Pad 2",
+					"geometry": "E8C064B6-3454-4739-9E02-3B07B8E70B4C",
+					"material": "FBDBE66D-B613-4741-802D-5AE1DE07DE46",
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,240,0,0,1]
+				},
+				{
+					"uuid": "C62AAE9F-9E51-46A5-BD2B-71BA804FC0B3",
+					"type": "DirectionalLight",
+					"name": "DirectionalLight 3",
+					"color": 16777215,
+					"intensity": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,100,200,150,1]
+				}]
+		}
+	},
+	"scripts": {
+		"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}"
+			}]
+	}
+}

+ 56 - 15
editor/index.html

@@ -19,7 +19,6 @@
 		<script src="../examples/js/loaders/ColladaLoader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
-		<script src="../examples/js/loaders/SceneLoader.js"></script>
 		<script src="../examples/js/loaders/STLLoader.js"></script>
 		<script src="../examples/js/loaders/UTF8Loader.js"></script>
 		<script src="../examples/js/loaders/VRMLLoader.js"></script>
@@ -30,20 +29,31 @@
 		<script src="../examples/js/exporters/OBJExporter.js"></script>
 		<script src="../examples/js/exporters/STLExporter.js"></script>
 
+		<script src="../examples/js/loaders/deprecated/SceneLoader.js"></script>
+
 		<script src="../examples/js/renderers/Projector.js"></script>
 		<script src="../examples/js/renderers/CanvasRenderer.js"></script>
 		<script src="../examples/js/renderers/RaytracingRenderer.js"></script>
 		<script src="../examples/js/renderers/SoftwareRenderer.js"></script>
 		<script src="../examples/js/renderers/SVGRenderer.js"></script>
 
+		<link rel="stylesheet" href="js/libs/codemirror/codemirror.css">
+		<link rel="stylesheet" href="js/libs/codemirror/theme/monokai.css">
+		<script src="js/libs/codemirror/codemirror.js"></script>
+		<script src="js/libs/codemirror/mode/javascript.js"></script>
+
 		<script src="js/libs/jszip.min.js"></script>
+		<script src="js/libs/sortable.min.js"></script>
 		<script src="js/libs/signals.min.js"></script>
 		<script src="js/libs/ui.js"></script>
-		<script src="js/libs/ui.editor.js"></script>
 		<script src="js/libs/ui.three.js"></script>
 
 		<script src="js/libs/app.js"></script>
 		<script src="js/Player.js"></script>
+		<script src="js/Script.js"></script>
+
+		<script src="../examples/js/effects/VREffect.js"></script>
+		<script src="../examples/js/controls/VRControls.js"></script>
 
 		<script src="js/Storage.js"></script>
 
@@ -56,10 +66,11 @@
 		<script src="js/Menubar.Add.js"></script>
 		<script src="js/Menubar.Play.js"></script>
 		<script src="js/Menubar.View.js"></script>
+		<script src="js/Menubar.Examples.js"></script>
 		<script src="js/Menubar.Help.js"></script>
 		<script src="js/Menubar.Status.js"></script>
 		<script src="js/Sidebar.js"></script>
-		<script src="js/Sidebar.Renderer.js"></script>
+		<script src="js/Sidebar.Project.js"></script>
 		<script src="js/Sidebar.Scene.js"></script>
 		<script src="js/Sidebar.Object3D.js"></script>
 		<script src="js/Sidebar.Animation.js"></script>
@@ -77,7 +88,6 @@
 		<script src="js/Sidebar.Geometry.TorusKnotGeometry.js"></script>
 		<script src="js/Sidebar.Material.js"></script>
 		<script src="js/Sidebar.Script.js"></script>
-		<script src="js/Sidebar.Script.Editor.js"></script>
 		<script src="js/Toolbar.js"></script>
 		<script src="js/Viewport.js"></script>
 		<script src="js/Viewport.Info.js"></script>
@@ -98,6 +108,9 @@
 			var viewport = new Viewport( editor );
 			document.body.appendChild( viewport.dom );
 
+			var script = new Script( editor );
+			document.body.appendChild( script.dom );
+
 			var player = new Player( editor );
 			document.body.appendChild( player.dom );
 
@@ -123,10 +136,7 @@
 
 					if ( state !== undefined ) {
 
-						var loader = new THREE.ObjectLoader();
-						var scene = loader.parse( state );
-
-						editor.setScene( scene );
+						editor.fromJSON( state );
 
 					}
 
@@ -160,7 +170,7 @@
 
 						timeout = setTimeout( function () {
 
-							editor.storage.set( editor.scene.toJSON() );
+							editor.storage.set( editor.toJSON() );
 
 							editor.signals.savingFinished.dispatch();
 
@@ -172,13 +182,16 @@
 
 				var signals = editor.signals;
 
+				signals.editorCleared.add( saveState );
 				signals.geometryChanged.add( saveState );
 				signals.objectAdded.add( saveState );
 				signals.objectChanged.add( saveState );
 				signals.objectRemoved.add( saveState );
 				signals.materialChanged.add( saveState );
 				signals.sceneGraphChanged.add( saveState );
+				signals.scriptChanged.add( saveState );
 
+				/*
 				var showDialog = function ( content ) {
 
 					dialog.clear();
@@ -189,6 +202,7 @@
 				};
 
 				signals.showDialog.add( showDialog );
+				*/
 
 			} );
 
@@ -204,7 +218,12 @@
 			document.addEventListener( 'drop', function ( event ) {
 
 				event.preventDefault();
-				editor.loader.loadFile( event.dataTransfer.files[ 0 ] );
+
+				if ( event.dataTransfer.files.length > 0 ) {
+
+					editor.loader.loadFile( event.dataTransfer.files[ 0 ] );
+
+				}
 
 			}, false );
 
@@ -215,11 +234,6 @@
 					case 8: // prevent browser back
 						event.preventDefault();
 						break;
-					case 46: // delete
-						var parent = editor.selected.parent;
-						editor.removeObject( editor.selected );
-						editor.select( parent );
-						break;
 
 				}
 
@@ -235,6 +249,33 @@
 
 			onWindowResize();
 
+			//
+
+			var file = null;
+			var hash = window.location.hash;
+
+			if ( hash.substr( 1, 4 ) === 'app=' ) file = hash.substr( 5 );
+			if ( hash.substr( 1, 6 ) === 'scene=' ) file = hash.substr( 7 );
+
+			if ( file !== null ) {
+
+				if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) {
+
+					var loader = new THREE.XHRLoader();
+					loader.crossOrigin = '';
+					loader.load( file, function ( text ) {
+
+						var json = JSON.parse( text );
+
+						editor.clear();
+						editor.fromJSON( json );
+
+					} );
+
+				}
+
+			}
+
 		</script>
 	</body>
 </html>

+ 6 - 5
editor/js/Config.js

@@ -9,10 +9,11 @@ var Config = function () {
 	var storage = {
 		'autosave': true,
 		'theme': 'css/light.css',
-		
-		'renderer': 'WebGLRenderer',
-		'renderer/antialias': true,
-	
+
+		'project/renderer': 'WebGLRenderer',
+		'project/renderer/antialias': true,
+		'project/vr': false,
+
 		'camera/position': [ 500, 250, 500 ],
 		'camera/target': [ 0, 0, 0 ],
 
@@ -20,7 +21,7 @@ var Config = function () {
 		'ui/sidebar/geometry/collapsed': true,
 		'ui/sidebar/material/collapsed': true,
 		'ui/sidebar/object3d/collapsed': false,
-		'ui/sidebar/renderer/collapsed': true,
+		'ui/sidebar/project/collapsed': true,
 		'ui/sidebar/scene/collapsed': false,
 		'ui/sidebar/script/collapsed': true
 	};

+ 132 - 11
editor/js/Editor.js

@@ -8,6 +8,10 @@ var Editor = function () {
 
 	this.signals = {
 
+		// script
+
+		editScript: new SIGNALS.Signal(),
+
 		// player
 
 		startPlayer: new SIGNALS.Signal(),
@@ -18,10 +22,12 @@ var Editor = function () {
 		playAnimation: new SIGNALS.Signal(),
 		stopAnimation: new SIGNALS.Signal(),
 
-		showDialog: new SIGNALS.Signal(),
+		// showDialog: new SIGNALS.Signal(),
 
 		// notifications
 
+		editorCleared: new SIGNALS.Signal(),
+
 		savingStarted: new SIGNALS.Signal(),
 		savingFinished: new SIGNALS.Signal(),
 
@@ -49,6 +55,11 @@ var Editor = function () {
 		helperRemoved: new SIGNALS.Signal(),
 
 		materialChanged: new SIGNALS.Signal(),
+
+		scriptAdded: new SIGNALS.Signal(),
+		scriptChanged: new SIGNALS.Signal(),
+		scriptRemoved: new SIGNALS.Signal(),
+
 		fogTypeChanged: new SIGNALS.Signal(),
 		fogColorChanged: new SIGNALS.Signal(),
 		fogParametersChanged: new SIGNALS.Signal(),
@@ -62,7 +73,7 @@ var Editor = function () {
 	this.storage = new Storage();
 	this.loader = new Loader( this );
 
-	this.camera = new THREE.PerspectiveCamera( 50, 1, 0.1, 100000 );
+	this.camera = new THREE.PerspectiveCamera( 50, 1, 1, 100000 );
 	this.camera.name = 'Camera';
 
 	this.scene = new THREE.Scene();
@@ -74,7 +85,7 @@ var Editor = function () {
 	this.geometries = {};
 	this.materials = {};
 	this.textures = {};
-	// this.scripts = {};
+	this.scripts = {};
 
 	this.selected = null;
 	this.helpers = {};
@@ -91,16 +102,19 @@ Editor.prototype = {
 
 	},
 
+	/*
 	showDialog: function ( value ) {
 
 		this.signals.showDialog.dispatch( value );
 
 	},
+	*/
 
 	//
 
 	setScene: function ( scene ) {
 
+		this.scene.uuid = scene.uuid;
 		this.scene.name = scene.name;
 		this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) );
 
@@ -141,7 +155,31 @@ Editor.prototype = {
 
 	},
 
-	setObjectName: function ( object, name ) {
+	moveObject: function ( object, parent, before ) {
+
+		if ( parent === undefined ) {
+
+			parent = this.scene;
+
+		}
+
+		parent.add( object );
+
+		// sort children array
+
+		if ( before !== undefined ) {
+
+			var index = parent.children.indexOf( before );
+			parent.children.splice( index, 0, object );
+			parent.children.pop();
+
+		}
+
+		this.signals.sceneGraphChanged.dispatch();
+
+	},
+
+	nameObject: function ( object, name ) {
 
 		object.name = name;
 		this.signals.sceneGraphChanged.dispatch();
@@ -152,8 +190,6 @@ Editor.prototype = {
 
 		if ( object.parent === undefined ) return; // avoid deleting the camera or scene
 
-		if ( confirm( 'Delete ' + object.name + '?' ) === false ) return;
-
 		var scope = this;
 
 		object.traverse( function ( child ) {
@@ -275,17 +311,33 @@ Editor.prototype = {
 
 	//
 
-	parent: function ( object, parent ) {
+	addScript: function ( object, script ) {
 
-		if ( parent === undefined ) {
+		if ( this.scripts[ object.uuid ] === undefined ) {
 
-			parent = this.scene;
+			this.scripts[ object.uuid ] = [];
 
 		}
 
-		parent.add( object );
+		this.scripts[ object.uuid ].push( script );
 
-		this.signals.sceneGraphChanged.dispatch();
+		this.signals.scriptAdded.dispatch( script );
+
+	},
+
+	removeScript: function ( object, script ) {
+
+		if ( this.scripts[ object.uuid ] === undefined ) return;
+
+		var index = this.scripts[ object.uuid ].indexOf( script );
+
+		if ( index !== - 1 ) {
+
+			this.scripts[ object.uuid ].splice( index, 1 );
+
+		}
+
+		this.signals.scriptRemoved.dispatch( script );
 
 	},
 
@@ -355,6 +407,75 @@ Editor.prototype = {
 
 		this.focus( this.scene.getObjectById( id, true ) );
 
+	},
+
+	clear: function () {
+
+		this.camera.position.set( 500, 250, 500 );
+		this.camera.lookAt( new THREE.Vector3() );
+
+		var objects = this.scene.children;
+
+		while ( objects.length > 0 ) {
+
+			this.removeObject( objects[ 0 ] );
+
+		}
+
+		this.geometries = {};
+		this.materials = {};
+		this.textures = {};
+		this.scripts = {};
+
+		this.deselect();
+
+		this.signals.editorCleared.dispatch();
+
+	},
+
+	//
+
+	fromJSON: function ( json ) {
+
+		var loader = new THREE.ObjectLoader();
+
+		// backwards
+
+		if ( json.scene === undefined ) {
+
+			var scene = loader.parse( json );
+
+			this.setScene( scene );
+
+			return;
+
+		}
+
+		// TODO: Clean this up somehow
+
+		var camera = loader.parse( json.camera );
+
+		this.camera.position.copy( camera.position );
+		this.camera.rotation.copy( camera.rotation );
+		this.camera.aspect = camera.aspect;
+		this.camera.near = camera.near;
+		this.camera.far = camera.far;
+
+		this.setScene( loader.parse( json.scene ) );
+		this.scripts = json.scripts;
+
+	},
+
+	toJSON: function () {
+
+		return {
+
+			camera: this.camera.toJSON(),
+			scene: this.scene.toJSON(),
+			scripts: this.scripts
+
+		};
+
 	}
 
 }

+ 29 - 4
editor/js/Menubar.Add.js

@@ -20,6 +20,15 @@ Menubar.Add = function ( editor ) {
 
 	var meshCount = 0;
 	var lightCount = 0;
+	var cameraCount = 0;
+
+	editor.signals.editorCleared.add( function () {
+
+		meshCount = 0;
+		lightCount = 0;
+		cameraCount = 0;
+
+	} );
 
 	// Group
 
@@ -227,10 +236,6 @@ Menubar.Add = function ( editor ) {
 	} );
 	options.add( option );
 
-	//
-
-	options.add( new UI.HorizontalRule() );
-
 	// Sprite
 
 	var option = new UI.Panel();
@@ -358,6 +363,26 @@ Menubar.Add = function ( editor ) {
 	} );
 	options.add( option );
 
+	//
+
+	options.add( new UI.HorizontalRule() );
+
+	// PerspectiveCamera
+
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'PerspectiveCamera' );
+	option.onClick( function() {
+
+		var camera = new THREE.PerspectiveCamera( 50, 1, 1, 10000 );
+		camera.name = 'PerspectiveCamera ' + ( ++ cameraCount );
+
+		editor.addObject( camera );
+		editor.select( camera );
+
+	} );
+	options.add( option );
+
 	return container;
 
 }

+ 6 - 2
editor/js/Menubar.Edit.js

@@ -41,9 +41,13 @@ Menubar.Edit = function ( editor ) {
 	option.setClass( 'option' );
 	option.setTextContent( 'Delete' );
 	option.onClick( function () {
+	
+		var object = editor.selected;
+
+		if ( confirm( 'Delete ' + object.name + '?' ) === false ) return;
 
-		var parent = editor.selected.parent;
-		editor.removeObject( editor.selected );
+		var parent = object.parent;
+		editor.removeObject( object );
 		editor.select( parent );
 
 	} );

+ 61 - 0
editor/js/Menubar.Examples.js

@@ -0,0 +1,61 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+Menubar.Examples = function ( editor ) {
+
+	var container = new UI.Panel();
+	container.setClass( 'menu' );
+
+	var title = new UI.Panel();
+	title.setClass( 'title' );
+	title.setTextContent( 'Examples' );
+	container.add( title );
+
+	var options = new UI.Panel();
+	options.setClass( 'options' );
+	container.add( options );
+
+	// Examples
+
+	var items = [
+		{ title: 'Arkanoid', file: 'arkanoid.app.json' },
+		{ title: 'Camera', file: 'camera.app.json' },
+		{ title: 'Particles', file: 'particles.app.json' },
+		{ title: 'Pong', file: 'pong.app.json' }
+	];
+
+	var loader = new THREE.XHRLoader();
+
+	for ( var i = 0; i < items.length; i ++ ) {
+
+		( function ( i ) {
+
+			var item = items[ i ];
+
+			var option = new UI.Panel();
+			option.setClass( 'option' );
+			option.setTextContent( item.title );
+			option.onClick( function () {
+
+				if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) {
+
+					loader.load( 'examples/' + item.file, function ( text ) {
+
+						editor.clear();
+						editor.fromJSON( JSON.parse( text ) );
+
+					} );
+
+				}
+
+			} );
+			options.add( option );
+
+		} )( i )
+
+	}
+
+	return container;
+
+};

+ 27 - 61
editor/js/Menubar.File.js

@@ -23,18 +23,9 @@ Menubar.File = function ( editor ) {
 	option.setTextContent( 'New' );
 	option.onClick( function () {
 
-		if ( confirm( 'Are you sure?' ) ) {
+		if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) {
 
-			editor.config.setKey(
-				'camera/position', [ 500, 250, 500 ],
-				'camera/target', [ 0, 0, 0 ]
-			);
-
-			editor.storage.clear( function () {
-
-				location.href = location.pathname;
-
-			} );
+			editor.clear();
 
 		}
 
@@ -98,7 +89,7 @@ Menubar.File = function ( editor ) {
 		output = JSON.stringify( output, null, '\t' );
 		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
 
-		exportString( output );
+		exportString( output, 'geometry.json' );
 
 	} );
 	options.add( option );
@@ -123,7 +114,7 @@ Menubar.File = function ( editor ) {
 		output = JSON.stringify( output, null, '\t' );
 		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
 
-		exportString( output );
+		exportString( output, 'model.json' );
 
 	} );
 	options.add( option );
@@ -139,7 +130,7 @@ Menubar.File = function ( editor ) {
 		output = JSON.stringify( output, null, '\t' );
 		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
 
-		exportString( output );
+		exportString( output, 'scene.json' );
 
 	} );
 	options.add( option );
@@ -162,7 +153,7 @@ Menubar.File = function ( editor ) {
 
 		var exporter = new THREE.OBJExporter();
 
-		exportString( exporter.parse( object ) );
+		exportString( exporter.parse( object ), 'model.obj' );
 
 	} );
 	options.add( option );
@@ -176,7 +167,7 @@ Menubar.File = function ( editor ) {
 
 		var exporter = new THREE.STLExporter();
 
-		exportString( exporter.parse( editor.scene ) );
+		exportString( exporter.parse( editor.scene ), 'model.stl' );
 
 	} );
 	options.add( option );
@@ -213,48 +204,21 @@ Menubar.File = function ( editor ) {
 			'	</head>',
 			'	<body ontouchstart="">',
 			'		<script src="js/three.min.js"></script>',
-			'		<script src="js/OrbitControls.js"></script>',
+			'		<script src="js/app.js"></script>',
 			'		<script>',
 			'',
-			'			var camera, controls, scene, renderer;',
-			'',
-			'			var loader = new THREE.ObjectLoader();',
-			'			loader.load( \'scene.json\', function ( object ) {',
-			'',
-			'				scene = object;',
+			'			var loader = new THREE.XHRLoader();',
+			'			loader.load( \'app.json\', function ( text ) {',
 			'',
-			'				camera = new THREE.PerspectiveCamera( ' + camera.fov + ', 1, ' + camera.near + ', ' + camera.far + ' );',
-			'				camera.position.set( ' + camera.position.x + ', ' + camera.position.y + ', ' + camera.position.z + ' );',
-			'				camera.rotation.set( ' + camera.rotation.x + ', ' + camera.rotation.y + ', ' + camera.rotation.z + ' );',
+			'				var player = new APP.Player();',
+			'				player.load( JSON.parse( text ) );',
+			'				player.setSize( window.innerWidth, window.innerHeight );',
+			'				player.play();',
 			'',
-			'				controls = new THREE.OrbitControls( camera );',
-			'				controls.addEventListener( \'change\', render );',
-			'',
-			'				renderer = new THREE.WebGLRenderer();',
-			'				renderer.setSize( window.innerWidth, window.innerHeight );',
-			'				document.body.appendChild( renderer.domElement );',
-			'',
-			'				camera.aspect = window.innerWidth / window.innerHeight;',
-			'				camera.updateProjectionMatrix();',
-			'',
-			'				animate();',
-			'				render();',
+			'				document.body.appendChild( player.dom );',
 			'',
 			'			} );',
 			'',
-			'			var render = function () {',
-			'',
-			'				renderer.render( scene, camera );',
-			'',
-			'			};',
-			'',
-			'			var animate = function () {',
-			'',
-			'				requestAnimationFrame( animate );',
-			'				controls.update();',
-			'',
-			'			};',
-			'',
 			'		</script>',
 			'	</body>',
 			'</html>'
@@ -263,11 +227,11 @@ Menubar.File = function ( editor ) {
 
 		//
 
-		var output = editor.scene.toJSON();
+		var output = editor.toJSON();
 		output = JSON.stringify( output, null, '\t' );
 		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
 
-		zip.file( 'scene.json', output );
+		zip.file( 'app.json', output );
 
 		//
 
@@ -278,14 +242,14 @@ Menubar.File = function ( editor ) {
 		} );
 
 		var loader = new THREE.XHRLoader( manager );
-		loader.load( '../build/three.min.js', function ( content ) {
+		loader.load( 'js/libs/app.js', function ( content ) {
 
-			zip.file( 'js/three.min.js', content );
+			zip.file( 'js/app.js', content );
 
 		} );
-		loader.load( '../examples/js/controls/OrbitControls.js', function ( content ) {
+		loader.load( '../build/three.min.js', function ( content ) {
 
-			zip.file( 'js/OrbitControls.js', content );
+			zip.file( 'js/three.min.js', content );
 
 		} );
 
@@ -308,16 +272,18 @@ Menubar.File = function ( editor ) {
 	*/
 
 
-
 	//
 
-	var exportString = function ( output ) {
+	var exportString = function ( output, filename ) {
 
 		var blob = new Blob( [ output ], { type: 'text/plain' } );
 		var objectURL = URL.createObjectURL( blob );
 
-		window.open( objectURL, '_blank' );
-		window.focus();
+		var link = document.createElement( 'a' );
+		link.href = objectURL;
+		link.download = filename || 'data.json';
+		link.target = '_blank';
+		link.click();
 
 	};
 

+ 1 - 1
editor/js/Menubar.Play.js

@@ -20,7 +20,7 @@ Menubar.Play = function ( editor ) {
 
 			isPlaying = true;
 			title.setTextContent( 'Stop' );
-			signals.startPlayer.dispatch( editor.scene.toJSON() );
+			signals.startPlayer.dispatch();
 
 		} else {
 

+ 34 - 0
editor/js/Menubar.View.js

@@ -42,6 +42,40 @@ Menubar.View = function ( editor ) {
 	} );
 	options.add( option );
 
+	//
+
+	options.add( new UI.HorizontalRule() );
+
+	// fullscreen
+
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'Fullscreen' );
+	option.onClick( function () {
+
+		var element = document.body;
+
+		if ( element.requestFullscreen ) {
+
+			element.requestFullscreen();
+
+		} else if ( element.mozRequestFullScreen ) {
+
+			element.mozRequestFullScreen();
+
+		} else if ( element.webkitRequestFullscreen ) {
+
+			element.webkitRequestFullscreen();
+
+		} else if ( element.msRequestFullscreen ) {
+
+			element.msRequestFullscreen();
+
+		}
+
+	} );
+	options.add( option );
+
 	return container;
 
 };

+ 1 - 0
editor/js/Menubar.js

@@ -11,6 +11,7 @@ var Menubar = function ( editor ) {
 	container.add( new Menubar.Edit( editor ) );
 	container.add( new Menubar.Add( editor ) );
 	container.add( new Menubar.Play( editor ) );
+	container.add( new Menubar.Examples( editor ) );
 	container.add( new Menubar.View( editor ) );
 	container.add( new Menubar.Help( editor ) );
 

+ 11 - 3
editor/js/Player.js

@@ -15,12 +15,20 @@ var Player = function ( editor ) {
 
 	var player = new APP.Player();
 
-	signals.startPlayer.add( function ( json ) {
+	window.addEventListener( 'resize', function () {
+
+		if ( player.dom === undefined ) return;
+
+		player.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
+
+	} );
+
+	signals.startPlayer.add( function () {
 
 		container.setDisplay( '' );
 
-		player.load( json );
-		player.setCamera( editor.camera );
+		player.setVR( editor.config.getKey( 'project/vr' ) );
+		player.load( editor.toJSON() );
 		player.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
 		player.play();
 

+ 91 - 0
editor/js/Script.js

@@ -0,0 +1,91 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+var Script = function ( editor ) {
+
+	var signals = editor.signals;
+
+	var container = new UI.Panel();
+	container.setId( 'script' );
+	container.setPosition( 'absolute' );
+	container.setBackgroundColor( '#272822' );
+	container.setDisplay( 'none' );
+
+	var header = new UI.Panel();
+	header.setPadding( '10px' );
+	container.add( header );
+	
+	var title = new UI.Text().setColor( '#fff' );
+	header.add( title );
+
+	var buttonSVG = ( function () {
+		var svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
+		svg.setAttribute( 'width', 32 );
+		svg.setAttribute( 'height', 32 );
+		var path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
+		path.setAttribute( 'd', 'M 12,12 L 22,22 M 22,12 12,22' );
+		path.setAttribute( 'stroke', '#fff' );
+		svg.appendChild( path );
+		return svg;
+	} )();
+
+	var close = new UI.Element( buttonSVG );
+	close.setPosition( 'absolute' );
+	close.setTop( '3px' );
+	close.setRight( '1px' );
+	close.setCursor( 'pointer' );
+	close.onClick( function () {
+
+		container.setDisplay( 'none' );
+
+	} );
+	header.add( close );
+
+	var delay;
+	var currentScript;
+
+	var codemirror = CodeMirror( container.dom, {
+		value: '',
+		lineNumbers: true,
+		matchBrackets: true,
+		indentWithTabs: true,
+		tabSize: 4,
+		indentUnit: 4
+	} );
+	codemirror.setOption( 'theme', 'monokai' );
+	codemirror.on( 'change', function () {
+
+		clearTimeout( delay );
+		delay = setTimeout( function () {
+
+			currentScript.source = codemirror.getValue();
+
+			signals.scriptChanged.dispatch( currentScript );
+
+		}, 300 );
+
+	});
+
+	//
+	
+	signals.editorCleared.add( function () {
+
+		container.setDisplay( 'none' );
+
+	} );
+
+	signals.editScript.add( function ( object, script ) {
+
+		container.setDisplay( '' );
+
+		currentScript = script;
+
+		title.setValue( object.name + ' / ' + script.name );
+		codemirror.setValue( script.source );
+
+	} );
+
+	return container;
+
+};

+ 2 - 2
editor/js/Sidebar.Geometry.BufferGeometry.js

@@ -9,7 +9,7 @@ Sidebar.Geometry.BufferGeometry = function ( signals ) {
 	// vertices
 
 	var verticesRow = new UI.Panel();
-	var vertices = new UI.Text().setColor( '#444' ).setFontSize( '12px' );
+	var vertices = new UI.Text().setFontSize( '12px' );
 
 	verticesRow.add( new UI.Text( 'Vertices' ).setWidth( '90px' ) );
 	verticesRow.add( vertices );
@@ -19,7 +19,7 @@ Sidebar.Geometry.BufferGeometry = function ( signals ) {
 	// faces
 
 	var facesRow = new UI.Panel();
-	var faces = new UI.Text().setColor( '#444' ).setFontSize( '12px' );
+	var faces = new UI.Text().setFontSize( '12px' );
 
 	facesRow.add( new UI.Text( 'Faces' ).setWidth( '90px' ) );
 	facesRow.add( faces );

+ 2 - 2
editor/js/Sidebar.Geometry.Geometry.js

@@ -9,7 +9,7 @@ Sidebar.Geometry.Geometry = function ( signals ) {
 	// vertices
 
 	var verticesRow = new UI.Panel();
-	var vertices = new UI.Text().setColor( '#444' ).setFontSize( '12px' );
+	var vertices = new UI.Text().setFontSize( '12px' );
 
 	verticesRow.add( new UI.Text( 'Vertices' ).setWidth( '90px' ) );
 	verticesRow.add( vertices );
@@ -19,7 +19,7 @@ Sidebar.Geometry.Geometry = function ( signals ) {
 	// faces
 
 	var facesRow = new UI.Panel();
-	var faces = new UI.Text().setColor( '#444' ).setFontSize( '12px' );
+	var faces = new UI.Text().setFontSize( '12px' );
 
 	facesRow.add( new UI.Text( 'Faces' ).setWidth( '90px' ) );
 	facesRow.add( faces );

+ 2 - 2
editor/js/Sidebar.Geometry.js

@@ -22,7 +22,7 @@ Sidebar.Geometry = function ( editor ) {
 	// uuid
 
 	var geometryUUIDRow = new UI.Panel();
-	var geometryUUID = new UI.Input().setWidth( '115px' ).setColor( '#444' ).setFontSize( '12px' ).setDisabled( true );
+	var geometryUUID = new UI.Input().setWidth( '115px' ).setFontSize( '12px' ).setDisabled( true );
 	var geometryUUIDRenew = new UI.Button( '⟳' ).setMarginLeft( '7px' ).onClick( function () {
 
 		geometryUUID.setValue( THREE.Math.generateUUID() );
@@ -40,7 +40,7 @@ Sidebar.Geometry = function ( editor ) {
 	// name
 
 	var geometryNameRow = new UI.Panel();
-	var geometryName = new UI.Input().setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( function () {
+	var geometryName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () {
 
 		editor.setGeometryName( editor.selected.geometry, geometryName.getValue() );
 

+ 28 - 39
editor/js/Sidebar.Material.js

@@ -40,7 +40,7 @@ Sidebar.Material = function ( editor ) {
 	// uuid
 
 	var materialUUIDRow = new UI.Panel();
-	var materialUUID = new UI.Input().setWidth( '115px' ).setColor( '#444' ).setFontSize( '12px' ).setDisabled( true );
+	var materialUUID = new UI.Input().setWidth( '115px' ).setFontSize( '12px' ).setDisabled( true );
 	var materialUUIDRenew = new UI.Button( '⟳' ).setMarginLeft( '7px' ).onClick( function () {
 
 		materialUUID.setValue( THREE.Math.generateUUID() );
@@ -57,7 +57,7 @@ Sidebar.Material = function ( editor ) {
 	// name
 
 	var materialNameRow = new UI.Panel();
-	var materialName = new UI.Input().setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( function () {
+	var materialName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () {
 
 		editor.setMaterialName( editor.selected.material, materialName.getValue() );
 
@@ -84,7 +84,7 @@ Sidebar.Material = function ( editor ) {
 		'ShaderMaterial': 'ShaderMaterial',
 		'SpriteMaterial': 'SpriteMaterial'
 
-	} ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
 
 	materialClassRow.add( new UI.Text( 'Type' ).setWidth( '90px' ) );
 	materialClassRow.add( materialClass );
@@ -101,16 +101,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialColorRow );
 
-	// ambient
-
-	var materialAmbientRow = new UI.Panel();
-	var materialAmbient = new UI.Color().onChange( update );
-
-	materialAmbientRow.add( new UI.Text( 'Ambient' ).setWidth( '90px' ) );
-	materialAmbientRow.add( materialAmbient );
-
-	container.add( materialAmbientRow );
-
 	// emissive
 
 	var materialEmissiveRow = new UI.Panel();
@@ -204,7 +194,7 @@ Sidebar.Material = function ( editor ) {
 
 	var materialMapRow = new UI.Panel();
 	var materialMapEnabled = new UI.Checkbox( false ).onChange( update );
-	var materialMap = new UI.Texture().setColor( '#444' ).onChange( update );
+	var materialMap = new UI.Texture().onChange( update );
 
 	materialMapRow.add( new UI.Text( 'Map' ).setWidth( '90px' ) );
 	materialMapRow.add( materialMapEnabled );
@@ -216,7 +206,7 @@ Sidebar.Material = function ( editor ) {
 
 	var materialAlphaMapRow = new UI.Panel();
 	var materialAlphaMapEnabled = new UI.Checkbox( false ).onChange( update );
-	var materialAlphaMap = new UI.Texture().setColor( '#444' ).onChange( update );
+	var materialAlphaMap = new UI.Texture().onChange( update );
 
 	materialAlphaMapRow.add( new UI.Text( 'Alpha Map' ).setWidth( '90px' ) );
 	materialAlphaMapRow.add( materialAlphaMapEnabled );
@@ -228,7 +218,7 @@ Sidebar.Material = function ( editor ) {
 
 	var materialLightMapRow = new UI.Panel();
 	var materialLightMapEnabled = new UI.Checkbox( false ).onChange( update );
-	var materialLightMap = new UI.Texture().setColor( '#444' ).onChange( update );
+	var materialLightMap = new UI.Texture().onChange( update );
 
 	materialLightMapRow.add( new UI.Text( 'Light Map' ).setWidth( '90px' ) );
 	materialLightMapRow.add( materialLightMapEnabled );
@@ -240,7 +230,7 @@ Sidebar.Material = function ( editor ) {
 
 	var materialBumpMapRow = new UI.Panel();
 	var materialBumpMapEnabled = new UI.Checkbox( false ).onChange( update );
-	var materialBumpMap = new UI.Texture().setColor( '#444' ).onChange( update );
+	var materialBumpMap = new UI.Texture().onChange( update );
 	var materialBumpScale = new UI.Number( 1 ).setWidth( '30px' ).onChange( update );
 
 	materialBumpMapRow.add( new UI.Text( 'Bump Map' ).setWidth( '90px' ) );
@@ -254,7 +244,7 @@ Sidebar.Material = function ( editor ) {
 
 	var materialNormalMapRow = new UI.Panel();
 	var materialNormalMapEnabled = new UI.Checkbox( false ).onChange( update );
-	var materialNormalMap = new UI.Texture().setColor( '#444' ).onChange( update );
+	var materialNormalMap = new UI.Texture().onChange( update );
 
 	materialNormalMapRow.add( new UI.Text( 'Normal Map' ).setWidth( '90px' ) );
 	materialNormalMapRow.add( materialNormalMapEnabled );
@@ -266,7 +256,7 @@ Sidebar.Material = function ( editor ) {
 
 	var materialSpecularMapRow = new UI.Panel();
 	var materialSpecularMapEnabled = new UI.Checkbox( false ).onChange( update );
-	var materialSpecularMap = new UI.Texture().setColor( '#444' ).onChange( update );
+	var materialSpecularMap = new UI.Texture().onChange( update );
 
 	materialSpecularMapRow.add( new UI.Text( 'Specular Map' ).setWidth( '90px' ) );
 	materialSpecularMapRow.add( materialSpecularMapEnabled );
@@ -278,7 +268,7 @@ Sidebar.Material = function ( editor ) {
 
 	var materialEnvMapRow = new UI.Panel();
 	var materialEnvMapEnabled = new UI.Checkbox( false ).onChange( update );
-	var materialEnvMap = new UI.Texture( THREE.SphericalReflectionMapping ).setColor( '#444' ).onChange( update );
+	var materialEnvMap = new UI.Texture( THREE.SphericalReflectionMapping ).onChange( update );
 	var materialReflectivity = new UI.Number( 1 ).setWidth( '30px' ).onChange( update );
 
 	materialEnvMapRow.add( new UI.Text( 'Env Map' ).setWidth( '90px' ) );
@@ -297,7 +287,7 @@ Sidebar.Material = function ( editor ) {
 		1: 'Back',
 		2: 'Double'
 
-	} ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
 
 	materialSideRow.add( new UI.Text( 'Side' ).setWidth( '90px' ) );
 	materialSideRow.add( materialSide );
@@ -313,7 +303,7 @@ Sidebar.Material = function ( editor ) {
 		1: 'Flat',
 		2: 'Smooth'
 
-	} ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
 
 	materialShadingRow.add( new UI.Text( 'Shading' ).setWidth( '90px' ) );
 	materialShadingRow.add( materialShading );
@@ -332,7 +322,7 @@ Sidebar.Material = function ( editor ) {
 		4: 'Multiply',
 		5: 'Custom'
 
-	} ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
 
 	materialBlendingRow.add( new UI.Text( 'Blending' ).setWidth( '90px' ) );
 	materialBlendingRow.add( materialBlending );
@@ -379,7 +369,7 @@ Sidebar.Material = function ( editor ) {
 
 		var geometry = object.geometry;
 		var material = object.material;
-		
+
 		var textureWarning = false;
 		var objectHasUvs = false;
 
@@ -408,12 +398,6 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
-			if ( material.ambient !== undefined ) {
-
-				material.ambient.setHex( materialAmbient.getHexValue() );
-
-			}
-
 			if ( material.emissive !== undefined ) {
 
 				material.emissive.setHex( materialEmissive.getHexValue() );
@@ -452,8 +436,20 @@ Sidebar.Material = function ( editor ) {
 
 			if ( material.vertexColors !== undefined ) {
 
-				material.vertexColors = parseInt( materialVertexColors.getValue() );
-				material.needsUpdate = true;
+				var vertexColors = parseInt( materialVertexColors.getValue() );
+
+				if ( material.vertexColors !== vertexColors ) {
+
+					if ( geometry instanceof THREE.Geometry ) {
+
+						geometry.groupsNeedUpdate = true;
+
+					}
+
+					material.vertexColors = vertexColors;
+					material.needsUpdate = true;
+
+				}
 
 			}
 
@@ -639,7 +635,6 @@ Sidebar.Material = function ( editor ) {
 		var properties = {
 			'name': materialNameRow,
 			'color': materialColorRow,
-			'ambient': materialAmbientRow,
 			'emissive': materialEmissiveRow,
 			'specular': materialSpecularRow,
 			'shininess': materialShininessRow,
@@ -703,12 +698,6 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
-			if ( material.ambient !== undefined ) {
-
-				materialAmbient.setHexValue( material.ambient.getHexString() );
-
-			}
-
 			if ( material.emissive !== undefined ) {
 
 				materialEmissive.setHexValue( material.emissive.getHexString() );

+ 74 - 9
editor/js/Sidebar.Object3D.js

@@ -17,12 +17,54 @@ Sidebar.Object3D = function ( editor ) {
 
 	var objectType = new UI.Text().setTextTransform( 'uppercase' );
 	container.addStatic( objectType );
+
+	var objectActions = new UI.Select().setPosition('absolute').setRight( '8px' ).setFontSize( '11px' );
+	objectActions.setOptions( {
+
+		'Actions': 'Actions',
+		'Reset Position': 'Reset Position',
+		'Reset Rotation': 'Reset Rotation',
+		'Reset Scale': 'Reset Scale'
+
+	} );
+	objectActions.onClick( function ( event ) {
+
+		event.stopPropagation(); // Avoid panel collapsing
+
+	} );
+	objectActions.onChange( function ( event ) {
+
+		var object = editor.selected;
+
+		switch ( this.getValue() ) {
+
+			case 'Reset Position':
+				object.position.set( 0, 0, 0 );
+				break;
+
+			case 'Reset Rotation':
+				object.rotation.set( 0, 0, 0 );
+				break;
+
+			case 'Reset Scale':
+				object.scale.set( 1, 1, 1 );
+				break;
+
+		}
+
+		this.setValue( 'Actions' );
+
+		signals.objectChanged.dispatch( object );
+
+	} );
+	container.addStatic( objectActions );
+
 	container.add( new UI.Break() );
 
 	// uuid
 
 	var objectUUIDRow = new UI.Panel();
-	var objectUUID = new UI.Input().setWidth( '115px' ).setColor( '#444' ).setFontSize( '12px' ).setDisabled( true );
+	var objectUUID = new UI.Input().setWidth( '115px' ).setFontSize( '12px' ).setDisabled( true );
 	var objectUUIDRenew = new UI.Button( '⟳' ).setMarginLeft( '7px' ).onClick( function () {
 
 		objectUUID.setValue( THREE.Math.generateUUID() );
@@ -40,9 +82,9 @@ Sidebar.Object3D = function ( editor ) {
 	// name
 
 	var objectNameRow = new UI.Panel();
-	var objectName = new UI.Input().setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( function () {
+	var objectName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () {
 
-			editor.setObjectName( editor.selected, objectName.getValue() );
+			editor.nameObject( editor.selected, objectName.getValue() );
 
 	} );
 
@@ -54,7 +96,7 @@ Sidebar.Object3D = function ( editor ) {
 	// parent
 
 	var objectParentRow = new UI.Panel();
-	var objectParent = new UI.Select().setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+	var objectParent = new UI.Select().setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
 
 	objectParentRow.add( new UI.Text( 'Parent' ).setWidth( '90px' ) );
 	objectParentRow.add( objectParent );
@@ -189,6 +231,16 @@ Sidebar.Object3D = function ( editor ) {
 
 	container.add( objectExponentRow );
 
+	// decay
+
+	var objectDecayRow = new UI.Panel();
+	var objectDecay = new UI.Number().setRange( 0, Infinity ).onChange( update );
+
+	objectDecayRow.add( new UI.Text( 'Decay' ).setWidth( '90px' ) );
+	objectDecayRow.add( objectDecay );
+
+	container.add( objectDecayRow );
+
 	// visible
 
 	var objectVisibleRow = new UI.Panel();
@@ -200,11 +252,11 @@ Sidebar.Object3D = function ( editor ) {
 	container.add( objectVisibleRow );
 
 	// user data
-	
+
 	var timeout;
 
 	var objectUserDataRow = new UI.Panel();
-	var objectUserData = new UI.TextArea().setWidth( '150px' ).setHeight( '40px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+	var objectUserData = new UI.TextArea().setWidth( '150px' ).setHeight( '40px' ).setFontSize( '12px' ).onChange( update );
 	objectUserData.onKeyUp( function () {
 
 		try {
@@ -294,7 +346,7 @@ Sidebar.Object3D = function ( editor ) {
 
 				if ( object.parent.id !== newParentId && object.id !== newParentId ) {
 
-					editor.parent( object, editor.scene.getObjectById( newParentId, true ) );
+					editor.moveObject( object, editor.scene.getObjectById( newParentId ) );
 
 				}
 
@@ -367,6 +419,12 @@ Sidebar.Object3D = function ( editor ) {
 
 			}
 
+			if ( object.decay !== undefined ) {
+
+				object.decay = objectDecay.getValue();
+
+			}
+
 			object.visible = objectVisible.getValue();
 
 			try {
@@ -397,7 +455,8 @@ Sidebar.Object3D = function ( editor ) {
 			'groundColor': objectGroundColorRow,
 			'distance' : objectDistanceRow,
 			'angle' : objectAngleRow,
-			'exponent' : objectExponentRow
+			'exponent' : objectExponentRow,
+			'decay' : objectDecayRow
 		};
 
 		for ( var property in properties ) {
@@ -546,6 +605,12 @@ Sidebar.Object3D = function ( editor ) {
 
 		}
 
+		if ( object.decay !== undefined ) {
+
+			objectDecay.setValue( object.decay );
+
+		}
+
 		objectVisible.setValue( object.visible );
 
 		try {
@@ -558,7 +623,7 @@ Sidebar.Object3D = function ( editor ) {
 
 		}
 
-		objectUserData.setBorderColor( '#ccc' );
+		objectUserData.setBorderColor( 'transparent' );
 		objectUserData.setBackgroundColor( '' );
 
 		updateTransformRows( object );

+ 27 - 12
editor/js/Sidebar.Renderer.js → editor/js/Sidebar.Project.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-Sidebar.Renderer = function ( editor ) {
+Sidebar.Project = function ( editor ) {
 
 	var signals = editor.signals;
 
@@ -17,14 +17,14 @@ Sidebar.Renderer = function ( editor ) {
 	};
 
 	var container = new UI.CollapsiblePanel();
-	container.setCollapsed( editor.config.getKey( 'ui/sidebar/renderer/collapsed' ) );
+	container.setCollapsed( editor.config.getKey( 'ui/sidebar/project/collapsed' ) );
 	container.onCollapsedChange( function ( boolean ) {
 
-		editor.config.setKey( 'ui/sidebar/renderer/collapsed', boolean );
+		editor.config.setKey( 'ui/sidebar/project/collapsed', boolean );
 
 	} );
 
-	container.addStatic( new UI.Text( 'RENDERER' ) );
+	container.addStatic( new UI.Text( 'PROJECT' ) );
 	container.add( new UI.Break() );
 
 	// class
@@ -40,30 +40,30 @@ Sidebar.Renderer = function ( editor ) {
 	}
 
 	var rendererTypeRow = new UI.Panel();
-	var rendererType = new UI.Select().setOptions( options ).setWidth( '150px' ).setColor( '#444' ).onChange( function () {
+	var rendererType = new UI.Select().setOptions( options ).setWidth( '150px' ).onChange( function () {
 
-		editor.config.setKey( 'renderer', this.getValue() );
+		editor.config.setKey( 'project/renderer', this.getValue() );
 		updateRenderer();
 
 	} );
 
-	rendererTypeRow.add( new UI.Text( 'Type' ).setWidth( '90px' ) );
+	rendererTypeRow.add( new UI.Text( 'Renderer' ).setWidth( '90px' ) );
 	rendererTypeRow.add( rendererType );
 
 	container.add( rendererTypeRow );
 
-	if ( editor.config.getKey( 'renderer' ) !== undefined ) {
+	if ( editor.config.getKey( 'project/renderer' ) !== undefined ) {
 
-		rendererType.setValue( editor.config.getKey( 'renderer' ) );
+		rendererType.setValue( editor.config.getKey( 'project/renderer' ) );
 
 	}
-	
+
 	// antialiasing
 
 	var rendererAntialiasRow = new UI.Panel();
-	var rendererAntialias = new UI.Checkbox( editor.config.getKey( 'renderer/antialias' ) ).setLeft( '100px' ).onChange( function () {
+	var rendererAntialias = new UI.Checkbox( editor.config.getKey( 'project/renderer/antialias' ) ).setLeft( '100px' ).onChange( function () {
 
-		editor.config.setKey( 'renderer/antialias', this.getValue() );
+		editor.config.setKey( 'project/renderer/antialias', this.getValue() );
 		// updateRenderer();
 
 	} );
@@ -73,6 +73,21 @@ Sidebar.Renderer = function ( editor ) {
 
 	container.add( rendererAntialiasRow );
 
+	// VR
+
+	var vrRow = new UI.Panel();
+	var vr = new UI.Checkbox( editor.config.getKey( 'project/vr' ) ).setLeft( '100px' ).onChange( function () {
+
+		editor.config.setKey( 'project/vr', this.getValue() );
+		// updateRenderer();
+
+	} );
+
+	vrRow.add( new UI.Text( 'VR' ).setWidth( '90px' ) );
+	vrRow.add( vr );
+
+	container.add( vrRow );
+
 	//
 
 	function updateRenderer() {

+ 4 - 4
editor/js/Sidebar.Scene.js

@@ -19,7 +19,7 @@ Sidebar.Scene = function ( editor ) {
 
 	var ignoreObjectSelectedSignal = false;
 
-	var outliner = new UI.FancySelect().setId( 'outliner' );
+	var outliner = new UI.Outliner( editor );
 	outliner.onChange( function () {
 
 		ignoreObjectSelectedSignal = true;
@@ -56,7 +56,7 @@ Sidebar.Scene = function ( editor ) {
 		'Fog': 'Linear',
 		'FogExp2': 'Exponential'
 
-	} ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' )
+	} ).setWidth( '150px' );
 	fogType.onChange( function () {
 
 		var type = fogType.getValue();
@@ -133,8 +133,8 @@ Sidebar.Scene = function ( editor ) {
 
 		var options = [];
 
-		options.push( { value: camera.id, html: '<span class="type ' + camera.type + '"></span> ' + camera.name } );
-		options.push( { value: scene.id, html: '<span class="type ' + scene.type + '"></span> ' + scene.name } );
+		// options.push( { value: camera.id, html: '<span class="type ' + camera.type + '"></span> ' + camera.name } );
+		options.push( { static: true, value: scene.id, html: '<span class="type ' + scene.type + '"></span> ' + scene.name } );
 
 		( function addObjects( objects, pad ) {
 

+ 0 - 46
editor/js/Sidebar.Script.Editor.js

@@ -1,46 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-Sidebar.Script.Editor = function ( editor ) {
-
-	var timeout;
-
-	var scriptSource = new UI.TextArea( 'javascript' ).setWidth( '240px' ).setHeight( '180px' ).setFontSize( '12px' );
-	scriptSource.onKeyUp( function () {
-
-		clearTimeout( timeout );
-
-		timeout = setTimeout( function () {
-
-			var object = editor.selected;
-			var source = scriptSource.getValue();
-
-			try {
-
-				var script = new Function( 'scene', 'time', source ).bind( object.clone() );
-				script( new THREE.Scene(), 0 );
-
-				scriptSource.dom.classList.add( 'success' );
-				scriptSource.dom.classList.remove( 'fail' );
-
-			} catch ( error ) {
-
-				scriptSource.dom.classList.remove( 'success' );
-				scriptSource.dom.classList.add( 'fail' );
-
-				return;
-
-			}
-
-			editor.scripts[ object.uuid ] = [ source ];
-
-			editor.signals.objectChanged.dispatch( object );
-
-		}, 500 );
-
-	} );
-
-	return scriptSource;
-
-}

+ 80 - 13
editor/js/Sidebar.Script.js

@@ -18,28 +18,92 @@ Sidebar.Script = function ( editor ) {
 	container.addStatic( new UI.Text( 'Script' ).setTextTransform( 'uppercase' ) );
 	container.add( new UI.Break() );
 
-	var source = new Sidebar.Script.Editor( editor );
-	container.add( source );
+	//
 
-	signals.objectSelected.add( function ( object ) {
+	var scriptsContainer = new UI.Panel();
+	container.add( scriptsContainer );
 
-		if ( object !== null ) {
+	var newScript = new UI.Button( 'New' );
+	newScript.onClick( function () {
 
-			container.setDisplay( 'block' );
+		var script = { name: '', source: 'function update( event ) {}' };
+		editor.addScript( editor.selected, script );
+
+	} );
+	container.add( newScript );
+
+	/*
+	var loadScript = new UI.Button( 'Load' );
+	loadScript.setMarginLeft( '4px' );
+	container.add( loadScript );
+	*/
+
+	//
+
+	function update() {
+
+		scriptsContainer.clear();
+
+		var object = editor.selected;
+		var scripts = editor.scripts[ object.uuid ];
+
+		if ( scripts !== undefined ) {
+
+			for ( var i = 0; i < scripts.length; i ++ ) {
+
+				( function ( object, script ) {
+
+					var name = new UI.Input( script.name ).setWidth( '130px' ).setFontSize( '12px' );
+					name.onChange( function () {
+
+						script.name = this.getValue();
+
+						signals.scriptChanged.dispatch();
+
+					} );
+					scriptsContainer.add( name );
 
-			/*
-			var scripts = editor.scripts[ object.uuid ];
+					var edit = new UI.Button( 'Edit' );
+					edit.setMarginLeft( '4px' );
+					edit.onClick( function () {
 
-			if ( scripts !== undefined ) {
+						signals.editScript.dispatch( object, script );
 
-				scriptSource.setValue( scripts[ 0 ] );
+					} );
+					scriptsContainer.add( edit );
 
-			} else {
+					var remove = new UI.Button( 'Remove' );
+					remove.setMarginLeft( '4px' );
+					remove.onClick( function () {
 
-				scriptSource.setValue( '' );
+						if ( confirm( 'Are you sure?' ) ) {
+
+							editor.removeScript( editor.selected, script );
+
+						}
+
+					} );
+					scriptsContainer.add( remove );
+
+					scriptsContainer.add( new UI.Break() );
+
+				} )( object, scripts[ i ] )
 
 			}
-			*/
+
+		}
+
+	}
+
+	// signals
+
+	signals.objectSelected.add( function ( object ) {
+
+		if ( object !== null ) {
+
+			container.setDisplay( 'block' );
+
+			update();
 
 		} else {
 
@@ -49,6 +113,9 @@ Sidebar.Script = function ( editor ) {
 
 	} );
 
+	signals.scriptAdded.add( update );
+	signals.scriptRemoved.add( update );
+
 	return container;
 
-}
+};

+ 1 - 1
editor/js/Sidebar.js

@@ -7,7 +7,7 @@ var Sidebar = function ( editor ) {
 	var container = new UI.Panel();
 	container.setId( 'sidebar' );
 
-	container.add( new Sidebar.Renderer( editor ) );
+	container.add( new Sidebar.Project( editor ) );
 	container.add( new Sidebar.Scene( editor ) );
 	container.add( new Sidebar.Object3D( editor ) );
 	container.add( new Sidebar.Geometry( editor ) );

+ 0 - 2
editor/js/Toolbar.js

@@ -62,8 +62,6 @@ var Toolbar = function ( editor ) {
 
 	}
 
-	update();
-
 	return container;
 
 }

+ 27 - 16
editor/js/Viewport.js

@@ -225,6 +225,13 @@ var Viewport = function ( editor ) {
 
 	// signals
 
+	signals.editorCleared.add( function () {
+
+		controls.center.set( 0, 0, 0 );
+		render();
+
+	} );
+
 	signals.themeChanged.add( function ( value ) {
 
 		switch ( value ) {
@@ -269,8 +276,6 @@ var Viewport = function ( editor ) {
 		container.dom.removeChild( renderer.domElement );
 
 		renderer = createRenderer( type, antialias );
-		renderer.setClearColor( clearColor );
-		renderer.setPixelRatio( window.devicePixelRatio );
 		renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
 
 		container.dom.appendChild( renderer.domElement );
@@ -323,11 +328,7 @@ var Viewport = function ( editor ) {
 
 			}
 
-			if ( object instanceof THREE.PerspectiveCamera === false ) {
-
-				transformControls.attach( object );
-
-			}
+			transformControls.attach( object );
 
 		}
 
@@ -341,7 +342,13 @@ var Viewport = function ( editor ) {
 
 	} );
 
-	signals.geometryChanged.add( render );
+	signals.geometryChanged.add( function ( geometry ) {
+
+		selectionBox.update( editor.selected );
+
+		render();
+
+	} );
 
 	signals.objectAdded.add( function ( object ) {
 
@@ -363,19 +370,21 @@ var Viewport = function ( editor ) {
 
 		transformControls.update();
 
-		if ( object !== camera ) {
+		if ( object.geometry !== undefined ) {
 
-			if ( object.geometry !== undefined ) {
+			selectionBox.update( object );
 
-				selectionBox.update( object );
+		}
 
-			}
+		if ( object instanceof THREE.PerspectiveCamera ) {
 
-			if ( editor.helpers[ object.id ] !== undefined ) {
+			object.updateProjectionMatrix();
 
-				editor.helpers[ object.id ].update();
+		}
 
-			}
+		if ( editor.helpers[ object.id ] !== undefined ) {
+
+			editor.helpers[ object.id ].update();
 
 		}
 
@@ -516,6 +525,8 @@ var Viewport = function ( editor ) {
 		}
 
 		var renderer = new THREE[ type ]( { antialias: antialias } );
+		renderer.setClearColor( clearColor );
+		renderer.setPixelRatio( window.devicePixelRatio );
 		renderer.autoClear = false;
 		renderer.autoUpdateScene = false;
 
@@ -524,7 +535,7 @@ var Viewport = function ( editor ) {
 	};
 
 	var clearColor;
-	var renderer = createRenderer( editor.config.getKey( 'renderer' ), editor.config.getKey( 'renderer/antialias' ) );
+	var renderer = createRenderer( editor.config.getKey( 'project/renderer' ), editor.config.getKey( 'project/renderer/antialias' ) );
 	container.dom.appendChild( renderer.domElement );
 
 	animate();

+ 188 - 46
editor/js/libs/app.js

@@ -2,88 +2,230 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-var APP = {};
+var APP = {
 
-APP.Player = function () {
+	Player: function () {
 
-	var loader = new THREE.ObjectLoader();
-	var camera, scene, renderer;
-	var scripts;
-	
-	this.dom = undefined;
+		var scope = this;
 
-	this.load = function ( json ) {
+		var loader = new THREE.ObjectLoader();
+		var camera, scene, renderer;
 
-		renderer = new THREE.WebGLRenderer( { antialias: true } );
+		var vr, controls;
 
-		scene = loader.parse( json );
+		var events = {};
 
-		/*
-		scripts = [];
+		this.dom = undefined;
 
-		scene.traverse( function ( child ) {
+		this.width = 500;
+		this.height = 500;
 
-			if ( child.script !== undefined ) {
+		this.load = function ( json ) {
 
-				var script = new Function( 'scene', 'time', child.script.source ).bind( child );
-				scripts.push( script );
+			renderer = new THREE.WebGLRenderer( { antialias: true } );
+			renderer.setClearColor( 0x000000 );
+			renderer.setPixelRatio( window.devicePixelRatio );
+
+			camera = loader.parse( json.camera );
+			scene = loader.parse( json.scene );
+
+			events = {
+				keydown: [],
+				keyup: [],
+				mousedown: [],
+				mouseup: [],
+				mousemove: [],
+				touchstart: [],
+				touchend: [],
+				touchmove: [],
+				update: []
+			};
+
+			for ( var uuid in json.scripts ) {
+
+				var object = scene.getObjectByProperty( 'uuid', uuid, true );
+
+				var scripts = json.scripts[ uuid ];
+
+				for ( var i = 0; i < scripts.length; i ++ ) {
+
+					var script = scripts[ i ];
+
+					var functions = ( new Function( 'player, scene, keydown, keyup, mousedown, mouseup, mousemove, touchstart, touchend, touchmove, update', script.source + '\nreturn { keydown: keydown, keyup: keyup, mousedown: mousedown, mouseup: mouseup, mousemove: mousemove, touchstart: touchstart, touchend: touchend, touchmove: touchmove, update: update };' ).bind( object ) )( this, scene );
+
+					for ( var name in functions ) {
+
+						if ( functions[ name ] === undefined ) continue;
+
+						if ( events[ name ] === undefined ) {
+
+							console.warn( 'APP.Player: event type not supported (', name, ')' );
+							continue;
+
+						}
+
+						events[ name ].push( functions[ name ].bind( object ) );
+
+					}
+
+				}
 
 			}
 
-		} );
-		*/
+			this.dom = renderer.domElement;
+
+			if ( vr === true ) {
+
+				controls = new THREE.VRControls( camera );
+				renderer = new THREE.VREffect( renderer );
+
+				this.dom.addEventListener( 'dblclick', function () {
 
-		this.dom = renderer.domElement;
+					renderer.setFullScreen( true );
 
-	};
+				} );
+			}
 
-	this.setCamera = function ( master ) {
+		};
 
-		camera = master.clone();
+		this.setCamera = function ( value ) {
 
-	};
+			camera = value;
+			camera.aspect = this.width / this.height;
+			camera.updateProjectionMatrix();
 
-	this.setSize = function ( width, height ) {
+		};
 
-		renderer.setSize( width, height );
+		this.setVR = function ( value ) {
 
-	};
+			vr = value;
 
-	var request;
+		};
 
-	var animate = function ( time ) {
+		this.setSize = function ( width, height ) {
 
-		request = requestAnimationFrame( animate );
+			if ( vr ) {
+				width = 1280;
+				height = 800;
+			}
 
-		/*
-		for ( var i = 0; i < scripts.length; i ++ ) {
+			this.width = width;
+			this.height = height;
 
-			scripts[ i ]( scene, time );
+			camera.aspect = this.width / this.height;
+			camera.updateProjectionMatrix();
 
-		}
-		*/
+			renderer.setSize( width, height );
 
-		renderer.render( scene, camera );
+		};
 
-	};
+		var dispatch = function ( array, event ) {
 
-	this.play = function () {
+			for ( var i = 0, l = array.length; i < l; i ++ ) {
 
-		request = requestAnimationFrame( animate );
+				array[ i ]( event );
 
-	};
+			}
 
-	this.stop = function () {
+		};
 
-		cancelAnimationFrame( request );
+		var prevTime, request;
 
-	};
+		var animate = function ( time ) {
 
-};
+			request = requestAnimationFrame( animate );
+
+			dispatch( events.update, { time: time, delta: time - prevTime } );
+
+			if ( vr ) controls.update();
+
+			renderer.render( scene, camera );
+
+			prevTime = time;
+
+		};
+
+		this.play = function () {
+
+			document.addEventListener( 'keydown', onDocumentKeyDown );
+			document.addEventListener( 'keyup', onDocumentKeyUp );
+			document.addEventListener( 'mousedown', onDocumentMouseDown );
+			document.addEventListener( 'mouseup', onDocumentMouseUp );
+			document.addEventListener( 'mousemove', onDocumentMouseMove );
+			document.addEventListener( 'touchstart', onDocumentTouchStart );
+			document.addEventListener( 'touchend', onDocumentTouchEnd );
+			document.addEventListener( 'touchmove', onDocumentTouchMove );
+
+			request = requestAnimationFrame( animate );
+			prevTime = performance.now();
+
+		};
+
+		this.stop = function () {
+
+			document.removeEventListener( 'keydown', onDocumentKeyDown );
+			document.removeEventListener( 'keyup', onDocumentKeyUp );
+			document.removeEventListener( 'mousedown', onDocumentMouseDown );
+			document.removeEventListener( 'mouseup', onDocumentMouseUp );
+			document.removeEventListener( 'mousemove', onDocumentMouseMove );
+			document.removeEventListener( 'touchstart', onDocumentTouchStart );
+			document.removeEventListener( 'touchend', onDocumentTouchEnd );
+			document.removeEventListener( 'touchmove', onDocumentTouchMove );
+
+			cancelAnimationFrame( request );
+
+		};
+
+		//
+
+		var onDocumentKeyDown = function ( event ) {
+
+			dispatch( events.keydown, event );
+
+		};
+
+		var onDocumentKeyUp = function ( event ) {
+
+			dispatch( events.keyup, event );
+
+		};
+
+		var onDocumentMouseDown = function ( event ) {
+
+			dispatch( events.mousedown, event );
+
+		};
+
+		var onDocumentMouseUp = function ( event ) {
+
+			dispatch( events.mouseup, event );
+
+		};
+
+		var onDocumentMouseMove = function ( event ) {
+
+			dispatch( events.mousemove, event );
+
+		};
+
+		var onDocumentTouchStart = function ( event ) {
+
+			dispatch( events.touchstart, event );
+
+		};
+
+		var onDocumentTouchEnd = function ( event ) {
+
+			dispatch( events.touchend, event );
+
+		};
+
+		var onDocumentTouchMove = function ( event ) {
+
+			dispatch( events.touchmove, event );
 
-APP.Script = function ( source ) {
+		};
 
-	this.uuid = THREE.Math.generateUUID();
-	this.source = source;
+	}
 
 };

+ 22 - 14
editor/js/libs/codemirror/codemirror.css

@@ -5,10 +5,6 @@
   font-family: monospace;
   height: 300px;
 }
-.CodeMirror-scroll {
-  /* Set scrolling behaviour here */
-  overflow: auto;
-}
 
 /* PADDING */
 
@@ -52,11 +48,15 @@
 .CodeMirror div.CodeMirror-secondarycursor {
   border-left: 1px solid silver;
 }
-.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
   width: auto;
   border: 0;
   background: #7e7;
 }
+.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
+  z-index: 1;
+}
+
 .cm-animate-fat-cursor {
   width: auto;
   border: 0;
@@ -83,7 +83,7 @@
 /* Can style cursor different in overwrite (non-insert) mode */
 div.CodeMirror-overwrite div.CodeMirror-cursor {}
 
-.cm-tab { display: inline-block; }
+.cm-tab { display: inline-block; text-decoration: inherit; }
 
 .CodeMirror-ruler {
   border-left: 1px solid #ccc;
@@ -121,6 +121,7 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
 .cm-header, .cm-strong {font-weight: bold;}
 .cm-em {font-style: italic;}
 .cm-link {text-decoration: underline;}
+.cm-strikethrough {text-decoration: line-through;}
 
 .cm-s-default .cm-error {color: #f00;}
 .cm-invalidchar {color: #f00;}
@@ -146,6 +147,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 }
 
 .CodeMirror-scroll {
+  overflow: scroll !important; /* Things will break if this is overridden */
   /* 30px is the magic margin used to hide the element's real scrollbars */
   /* See overflow: hidden in .CodeMirror */
   margin-bottom: -30px; margin-right: -30px;
@@ -190,7 +192,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 
 .CodeMirror-gutters {
   position: absolute; left: 0; top: 0;
-  padding-bottom: 30px;
   z-index: 3;
 }
 .CodeMirror-gutter {
@@ -198,13 +199,17 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
   height: 100%;
   -moz-box-sizing: content-box;
   box-sizing: content-box;
-  padding-bottom: 30px;
-  margin-bottom: -32px;
   display: inline-block;
+  margin-bottom: -30px;
   /* Hack to make IE7 behave */
   *zoom:1;
   *display:inline;
 }
+.CodeMirror-gutter-wrapper {
+  position: absolute;
+  z-index: 4;
+  height: 100%;
+}
 .CodeMirror-gutter-elt {
   position: absolute;
   cursor: default;
@@ -213,6 +218,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 
 .CodeMirror-lines {
   cursor: text;
+  min-height: 1px; /* prevents collapsing before first draw */
 }
 .CodeMirror pre {
   /* Reset some styles that the rest of the page might have set */
@@ -250,10 +256,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 
 .CodeMirror-widget {}
 
-.CodeMirror-wrap .CodeMirror-scroll {
-  overflow-x: hidden;
-}
-
 .CodeMirror-measure {
   position: absolute;
   width: 100%;
@@ -272,7 +274,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 div.CodeMirror-cursors {
   visibility: hidden;
   position: relative;
-  z-index: 1;
+  z-index: 3;
 }
 .CodeMirror-focused div.CodeMirror-cursors {
   visibility: visible;
@@ -299,3 +301,9 @@ div.CodeMirror-cursors {
     visibility: hidden;
   }
 }
+
+/* See issue #2901 */
+.cm-tab-wrap-hack:after { content: ''; }
+
+/* Help users use markselection to safely style text background */
+span.CodeMirror-selectedtext { background: none; }

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 344 - 229
editor/js/libs/codemirror/codemirror.js


+ 8 - 8
editor/js/libs/codemirror/modes/javascript.js → editor/js/libs/codemirror/mode/javascript.js

@@ -19,7 +19,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
   var jsonldMode = parserConfig.jsonld;
   var jsonMode = parserConfig.json || jsonldMode;
   var isTS = parserConfig.typescript;
-  var wordRE = parserConfig.wordCharacters || /[\w$]/;
+  var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
 
   // Tokenizer
 
@@ -205,6 +205,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
         ++depth;
       } else if (wordRE.test(ch)) {
         sawSomething = true;
+      } else if (/["'\/]/.test(ch)) {
+        return;
       } else if (sawSomething && !depth) {
         ++pos;
         break;
@@ -391,7 +393,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
   function maybeoperatorNoComma(type, value, noComma) {
     var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
     var expr = noComma == false ? expression : expressionNoComma;
-    if (value == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
+    if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
     if (type == "operator") {
       if (/\+\+|--/.test(value)) return cont(me);
       if (value == "?") return cont(expression, expect(":"), expr);
@@ -417,13 +419,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
   }
   function arrowBody(type) {
     findFatArrow(cx.stream, cx.state);
-    if (type == "{") return pass(statement);
-    return pass(expression);
+    return pass(type == "{" ? statement : expression);
   }
   function arrowBodyNoComma(type) {
     findFatArrow(cx.stream, cx.state);
-    if (type == "{") return pass(statement);
-    return pass(expressionNoComma);
+    return pass(type == "{" ? statement : expressionNoComma);
   }
   function maybelabel(type) {
     if (type == ":") return cont(poplex, statement);
@@ -592,7 +592,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
   }
   function maybeArrayComprehension(type) {
     if (type == "for") return pass(comprehension, expect("]"));
-    if (type == ",") return cont(commasep(expressionNoComma, "]"));
+    if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
     return pass(commasep(expressionNoComma, "]"));
   }
   function comprehension(type) {
@@ -658,7 +658,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
       else return lexical.indented + (closing ? 0 : indentUnit);
     },
 
-    electricChars: ":{}",
+    electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
     blockCommentStart: jsonMode ? null : "/*",
     blockCommentEnd: jsonMode ? null : "*/",
     lineComment: jsonMode ? null : "//",

+ 31 - 0
editor/js/libs/codemirror/theme/monokai.css

@@ -0,0 +1,31 @@
+/* Based on Sublime Text's Monokai theme */
+
+.cm-s-monokai.CodeMirror {background: #272822; color: #f8f8f2;}
+.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
+.cm-s-monokai .CodeMirror-gutters {background: #272822; border-right: 0px;}
+.cm-s-monokai .CodeMirror-guttermarker { color: white; }
+.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
+.cm-s-monokai .CodeMirror-linenumber {color: #d0d0d0;}
+.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
+
+.cm-s-monokai span.cm-comment {color: #75715e;}
+.cm-s-monokai span.cm-atom {color: #ae81ff;}
+.cm-s-monokai span.cm-number {color: #ae81ff;}
+
+.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
+.cm-s-monokai span.cm-keyword {color: #f92672;}
+.cm-s-monokai span.cm-string {color: #e6db74;}
+
+.cm-s-monokai span.cm-variable {color: #a6e22e;}
+.cm-s-monokai span.cm-variable-2 {color: #9effff;}
+.cm-s-monokai span.cm-def {color: #fd971f;}
+.cm-s-monokai span.cm-bracket {color: #f8f8f2;}
+.cm-s-monokai span.cm-tag {color: #f92672;}
+.cm-s-monokai span.cm-link {color: #ae81ff;}
+.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
+
+.cm-s-monokai .CodeMirror-activeline-background {background: #373831 !important;}
+.cm-s-monokai .CodeMirror-matchingbracket {
+  text-decoration: underline;
+  color: white !important;
+}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1 - 0
editor/js/libs/sortable.min.js


+ 0 - 75
editor/js/libs/ui.editor.js

@@ -1,75 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- */
-
-UI.CodeEditor = function ( mode ) {
-
-	UI.Element.call( this );
-
-	var scope = this;
-
-	var dom = document.createElement( 'div' );
-	dom.className = 'CodeEditor';
-
-	var editor = CodeMirror( dom, { mode: mode, indentWithTabs: true, lineWrapping: true, matchBrackets: true } );
-	editor.onKeyUp( 'keyup', function () {
-
-		if ( scope.onKeyUpCallback !== undefined ) {
-
-			scope.onKeyUpCallback();
-
-		}
-
-	});
-
-	this.dom = dom;
-	this.editor = editor;
-
-	return this;
-
-};
-
-UI.CodeEditor.prototype = Object.create( UI.Element.prototype );
-UI.CodeEditor.prototype.constructor = UI.CodeEditor;
-
-UI.CodeEditor.prototype.setWidth = function ( value ) {
-
-	UI.Element.prototype.setWidth.call( this, value );
-
-	this.editor.setSize( this.dom.style.width, this.dom.style.height );
-
-	return this;
-
-};
-
-UI.CodeEditor.prototype.setHeight = function ( value ) {
-
-	UI.Element.prototype.setHeight.call( this, value );
-
-	this.editor.setSize( this.dom.style.width, this.dom.style.height );
-
-	return this;
-
-};
-
-UI.CodeEditor.prototype.getValue = function () {
-
-	return this.editor.getValue();
-
-};
-
-UI.CodeEditor.prototype.setValue = function ( value ) {
-
-	this.editor.setValue( value );
-
-	return this;
-
-};
-
-UI.CodeEditor.prototype.onKeyUp = function ( callback ) {
-
-	this.onKeyUpCallback = callback;
-
-	return this;
-
-};

+ 31 - 177
editor/js/libs/ui.js

@@ -4,14 +4,18 @@
 
 var UI = {};
 
-UI.Element = function () {};
+UI.Element = function ( dom ) {
+
+	this.dom = dom;
+
+};
 
 UI.Element.prototype = {
 
 	setId: function ( id ) {
 
 		this.dom.id = id;
-		
+
 		return this;
 
 	},
@@ -56,7 +60,7 @@ UI.Element.prototype = {
 
 var properties = [ 'position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', 'borderLeft',
 'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'color',
-'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor' ];
+'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex' ];
 
 properties.forEach( function ( property ) {
 
@@ -133,7 +137,7 @@ UI.Panel.prototype.add = function () {
 UI.Panel.prototype.remove = function () {
 
 	for ( var i = 0; i < arguments.length; i ++ ) {
-	
+
 		var argument = arguments[ i ];
 
 		if ( argument instanceof UI.Element ) {
@@ -307,6 +311,12 @@ UI.Text = function ( text ) {
 UI.Text.prototype = Object.create( UI.Element.prototype );
 UI.Text.prototype.constructor = UI.Text;
 
+UI.Text.prototype.getValue = function () {
+
+	return this.dom.textContent;
+
+};
+
 UI.Text.prototype.setValue = function ( value ) {
 
 	if ( value !== undefined ) {
@@ -322,7 +332,7 @@ UI.Text.prototype.setValue = function ( value ) {
 
 // Input
 
-UI.Input = function () {
+UI.Input = function ( text ) {
 
 	UI.Element.call( this );
 
@@ -331,7 +341,7 @@ UI.Input = function () {
 	var dom = document.createElement( 'input' );
 	dom.className = 'Input';
 	dom.style.padding = '2px';
-	dom.style.border = '1px solid #ccc';
+	dom.style.border = '1px solid transparent';
 
 	dom.addEventListener( 'keydown', function ( event ) {
 
@@ -340,6 +350,7 @@ UI.Input = function () {
 	}, false );
 
 	this.dom = dom;
+	this.setValue( text );
 
 	return this;
 
@@ -374,7 +385,6 @@ UI.TextArea = function () {
 	var dom = document.createElement( 'textarea' );
 	dom.className = 'TextArea';
 	dom.style.padding = '2px';
-	dom.style.border = '1px solid #ccc';
 	dom.spellcheck = false;
 
 	dom.addEventListener( 'keydown', function ( event ) {
@@ -429,10 +439,7 @@ UI.Select = function () {
 
 	var dom = document.createElement( 'select' );
 	dom.className = 'Select';
-	dom.style.width = '64px';
-	dom.style.height = '16px';
-	dom.style.border = '0px';
-	dom.style.padding = '0px';
+	dom.style.padding = '2px';
 
 	this.dom = dom;
 
@@ -496,159 +503,6 @@ UI.Select.prototype.setValue = function ( value ) {
 
 };
 
-// FancySelect
-
-UI.FancySelect = function () {
-
-	UI.Element.call( this );
-
-	var scope = this;
-
-	var dom = document.createElement( 'div' );
-	dom.className = 'FancySelect';
-	dom.tabIndex = 0;	// keyup event is ignored without setting tabIndex
-
-	// Broadcast for object selection after arrow navigation
-	var changeEvent = document.createEvent('HTMLEvents');
-	changeEvent.initEvent( 'change', true, true );
-
-	// Prevent native scroll behavior
-	dom.addEventListener( 'keydown', function (event) {
-
-		switch ( event.keyCode ) {
-			case 38: // up
-			case 40: // down
-				event.preventDefault();
-				event.stopPropagation();
-				break;
-		}
-
-	}, false);
-
-	// Keybindings to support arrow navigation
-	dom.addEventListener( 'keyup', function (event) {
-
-		switch ( event.keyCode ) {
-			case 38: // up
-			case 40: // down
-				scope.selectedIndex += ( event.keyCode == 38 ) ? -1 : 1;
-
-				if ( scope.selectedIndex >= 0 && scope.selectedIndex < scope.options.length ) {
-
-					// Highlight selected dom elem and scroll parent if needed
-					scope.setValue( scope.options[ scope.selectedIndex ].value );
-
-					scope.dom.dispatchEvent( changeEvent );
-
-				}
-
-				break;
-		}
-
-	}, false);
-
-	this.dom = dom;
-
-	this.options = [];
-	this.selectedIndex = -1;
-	this.selectedValue = null;
-
-	return this;
-
-};
-
-UI.FancySelect.prototype = Object.create( UI.Element.prototype );
-UI.FancySelect.prototype.constructor = UI.FancySelect;
-
-UI.FancySelect.prototype.setOptions = function ( options ) {
-
-	var scope = this;
-
-	var changeEvent = document.createEvent( 'HTMLEvents' );
-	changeEvent.initEvent( 'change', true, true );
-
-	while ( scope.dom.children.length > 0 ) {
-
-		scope.dom.removeChild( scope.dom.firstChild );
-
-	}
-
-	scope.options = [];
-
-	for ( var i = 0; i < options.length; i ++ ) {
-
-		var option = options[ i ];
-
-		var div = document.createElement( 'div' );
-		div.className = 'option';
-		div.innerHTML = option.html;
-		div.value = option.value;
-		scope.dom.appendChild( div );
-
-		scope.options.push( div );
-
-		div.addEventListener( 'click', function ( event ) {
-
-			scope.setValue( this.value );
-			scope.dom.dispatchEvent( changeEvent );
-
-		}, false );
-
-	}
-
-	return scope;
-
-};
-
-UI.FancySelect.prototype.getValue = function () {
-
-	return this.selectedValue;
-
-};
-
-UI.FancySelect.prototype.setValue = function ( value ) {
-
-	for ( var i = 0; i < this.options.length; i ++ ) {
-
-		var element = this.options[ i ];
-
-		if ( element.value === value ) {
-
-			element.classList.add( 'active' );
-
-			// scroll into view
-
-			var y = element.offsetTop - this.dom.offsetTop;
-			var bottomY = y + element.offsetHeight;
-			var minScroll = bottomY - this.dom.offsetHeight;
-
-			if ( this.dom.scrollTop > y ) {
-
-				this.dom.scrollTop = y
-
-			} else if ( this.dom.scrollTop < minScroll ) {
-
-				this.dom.scrollTop = minScroll;
-
-			}
-
-			this.selectedIndex = i;
-
-		} else {
-
-			element.classList.remove( 'active' );
-
-		}
-
-	}
-
-	this.selectedValue = value;
-
-	return this;
-
-};
-
-
 // Checkbox
 
 UI.Checkbox = function ( boolean ) {
@@ -786,8 +640,8 @@ UI.Number = function ( number ) {
 	var distance = 0;
 	var onMouseDownValue = 0;
 
-	var pointer = new THREE.Vector2();
-	var prevPointer = new THREE.Vector2();
+	var pointer = [ 0, 0 ];
+	var prevPointer = [ 0, 0 ];
 
 	var onMouseDown = function ( event ) {
 
@@ -797,7 +651,7 @@ UI.Number = function ( number ) {
 
 		onMouseDownValue = parseFloat( dom.value );
 
-		prevPointer.set( event.clientX, event.clientY );
+		prevPointer = [ event.clientX, event.clientY ];
 
 		document.addEventListener( 'mousemove', onMouseMove, false );
 		document.addEventListener( 'mouseup', onMouseUp, false );
@@ -808,9 +662,9 @@ UI.Number = function ( number ) {
 
 		var currentValue = dom.value;
 
-		pointer.set( event.clientX, event.clientY );
+		pointer = [ event.clientX, event.clientY ];
 
-		distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
+		distance += ( pointer[ 0 ] - prevPointer[ 0 ] ) - ( pointer[ 1 ] - prevPointer[ 1 ] );
 
 		var number = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
 
@@ -818,7 +672,7 @@ UI.Number = function ( number ) {
 
 		if ( currentValue !== dom.value ) dom.dispatchEvent( changeEvent );
 
-		prevPointer.set( event.clientX, event.clientY );
+		prevPointer = [ event.clientX, event.clientY ];
 
 	};
 
@@ -950,8 +804,8 @@ UI.Integer = function ( number ) {
 	var distance = 0;
 	var onMouseDownValue = 0;
 
-	var pointer = new THREE.Vector2();
-	var prevPointer = new THREE.Vector2();
+	var pointer = [ 0, 0 ];
+	var prevPointer = [ 0, 0 ];
 
 	var onMouseDown = function ( event ) {
 
@@ -961,7 +815,7 @@ UI.Integer = function ( number ) {
 
 		onMouseDownValue = parseFloat( dom.value );
 
-		prevPointer.set( event.clientX, event.clientY );
+		prevPointer = [ event.clientX, event.clientY ];
 
 		document.addEventListener( 'mousemove', onMouseMove, false );
 		document.addEventListener( 'mouseup', onMouseUp, false );
@@ -972,9 +826,9 @@ UI.Integer = function ( number ) {
 
 		var currentValue = dom.value;
 
-		pointer.set( event.clientX, event.clientY );
+		pointer = [ event.clientX, event.clientY ];
 
-		distance += ( pointer.x - prevPointer.x ) - ( pointer.y - prevPointer.y );
+		distance += ( pointer[ 0 ] - prevPointer[ 0 ] ) - ( pointer[ 1 ] - prevPointer[ 1 ] );
 
 		var number = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
 
@@ -982,7 +836,7 @@ UI.Integer = function ( number ) {
 
 		if ( currentValue !== dom.value ) dom.dispatchEvent( changeEvent );
 
-		prevPointer.set( event.clientX, event.clientY );
+		prevPointer = [ event.clientX, event.clientY ];
 
 	};
 
@@ -1147,7 +1001,7 @@ UI.Button.prototype.setLabel = function ( value ) {
 UI.Dialog = function ( value ) {
 
 	var scope = this;
-	
+
 	var dom = document.createElement( 'dialog' );
 
 	if ( dom.showModal === undefined ) {

+ 176 - 0
editor/js/libs/ui.three.js

@@ -133,3 +133,179 @@ UI.Texture.prototype.onChange = function ( callback ) {
 	return this;
 
 };
+
+// Outliner
+
+UI.Outliner = function ( editor ) {
+
+	UI.Element.call( this );
+
+	var scope = this;
+
+	var dom = document.createElement( 'div' );
+	dom.className = 'Outliner';
+	dom.tabIndex = 0;	// keyup event is ignored without setting tabIndex
+
+	var scene = editor.scene;
+
+	var sortable = Sortable.create( dom, {
+		draggable: '.draggable',
+		onUpdate: function ( event ) {
+
+			var item = event.item;
+
+			var object = scene.getObjectById( item.value );
+
+			if ( item.nextSibling === null ) {
+
+				editor.moveObject( object, editor.scene );
+
+			} else {
+
+				var nextObject = scene.getObjectById( item.nextSibling.value );
+				editor.moveObject( object, nextObject.parent, nextObject );
+
+			}
+
+		}
+	} );
+
+	// Broadcast for object selection after arrow navigation
+	var changeEvent = document.createEvent('HTMLEvents');
+	changeEvent.initEvent( 'change', true, true );
+
+	// Prevent native scroll behavior
+	dom.addEventListener( 'keydown', function (event) {
+
+		switch ( event.keyCode ) {
+			case 38: // up
+			case 40: // down
+			event.preventDefault();
+			event.stopPropagation();
+			break;
+		}
+
+	}, false);
+
+	// Keybindings to support arrow navigation
+	dom.addEventListener( 'keyup', function (event) {
+
+		switch ( event.keyCode ) {
+			case 38: // up
+			case 40: // down
+			scope.selectedIndex += ( event.keyCode == 38 ) ? -1 : 1;
+
+			if ( scope.selectedIndex >= 0 && scope.selectedIndex < scope.options.length ) {
+
+				// Highlight selected dom elem and scroll parent if needed
+				scope.setValue( scope.options[ scope.selectedIndex ].value );
+
+				scope.dom.dispatchEvent( changeEvent );
+
+			}
+
+			break;
+		}
+
+	}, false);
+
+	this.dom = dom;
+
+	this.options = [];
+	this.selectedIndex = -1;
+	this.selectedValue = null;
+
+	return this;
+
+};
+
+UI.Outliner.prototype = Object.create( UI.Element.prototype );
+UI.Outliner.prototype.constructor = UI.Outliner;
+
+UI.Outliner.prototype.setOptions = function ( options ) {
+
+	var scope = this;
+
+	var changeEvent = document.createEvent( 'HTMLEvents' );
+	changeEvent.initEvent( 'change', true, true );
+
+	while ( scope.dom.children.length > 0 ) {
+
+		scope.dom.removeChild( scope.dom.firstChild );
+
+	}
+
+	scope.options = [];
+
+	for ( var i = 0; i < options.length; i ++ ) {
+
+		var option = options[ i ];
+
+		var div = document.createElement( 'div' );
+		div.className = 'option ' + ( option.static === true ? '': 'draggable' );
+		div.innerHTML = option.html;
+		div.value = option.value;
+		scope.dom.appendChild( div );
+
+		scope.options.push( div );
+
+		div.addEventListener( 'click', function ( event ) {
+
+			scope.setValue( this.value );
+			scope.dom.dispatchEvent( changeEvent );
+
+		}, false );
+
+	}
+
+	return scope;
+
+};
+
+UI.Outliner.prototype.getValue = function () {
+
+	return this.selectedValue;
+
+};
+
+UI.Outliner.prototype.setValue = function ( value ) {
+
+	for ( var i = 0; i < this.options.length; i ++ ) {
+
+		var element = this.options[ i ];
+
+		if ( element.value === value ) {
+
+			element.classList.add( 'active' );
+
+			// scroll into view
+
+			var y = element.offsetTop - this.dom.offsetTop;
+			var bottomY = y + element.offsetHeight;
+			var minScroll = bottomY - this.dom.offsetHeight;
+
+			if ( this.dom.scrollTop > y ) {
+
+				this.dom.scrollTop = y
+
+			} else if ( this.dom.scrollTop < minScroll ) {
+
+				this.dom.scrollTop = minScroll;
+
+			}
+
+			this.selectedIndex = i;
+
+		} else {
+
+			element.classList.remove( 'active' );
+
+		}
+
+	}
+
+	this.selectedValue = value;
+
+	return this;
+
+};

+ 1 - 0
examples/canvas_ascii_effect.html

@@ -82,6 +82,7 @@
 				scene.add( plane );
 
 				renderer = new THREE.CanvasRenderer();
+				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setSize( width, height );
 				// container.appendChild( renderer.domElement );
 

+ 1 - 2
examples/canvas_lines_colors_2d.html

@@ -80,8 +80,7 @@
 
 				scene = new THREE.Scene();
 
-				renderer = new THREE.CanvasRenderer( { antialias: false } );
-				renderer.setClearColor( 0x000000, 1 );
+				renderer = new THREE.CanvasRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_lines_dashed.html

@@ -99,7 +99,7 @@
 				scene.add( object );
 
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0x111111, 1 );
+				renderer.setClearColor( 0x111111 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( WIDTH, HEIGHT );
 

+ 6 - 4
examples/index.html

@@ -183,7 +183,7 @@
 			</a>
 			<div id="content"></div>
 		</div>
-		<iframe id="viewer" allowfullscreen></iframe>
+		<iframe id="viewer" allowfullscreen onmousewheel=""></iframe>
 
 		<script>
 
@@ -197,6 +197,7 @@
 				"webgl_buffergeometry_lines",
 				"webgl_buffergeometry_lines_indexed",
 				"webgl_buffergeometry_particles",
+				"webgl_buffergeometry_drawcalls",
 				"webgl_buffergeometry_rawshader",
 				"webgl_buffergeometry_uint",
 				"webgl_camera",
@@ -208,10 +209,8 @@
 				"webgl_custom_attributes_particles3",
 				"webgl_decals",
 				"webgl_effects_anaglyph",
-				"webgl_effects_oculusrift",
 				"webgl_effects_parallaxbarrier",
 				"webgl_effects_stereo",
-				"webgl_effects_vr",
 				"webgl_geometries",
 				"webgl_geometries2",
 				"webgl_geometry_colors",
@@ -358,6 +357,7 @@
 				"webgl_shaders_vector",
 				"webgl_shadowmap",
 				"webgl_shadowmap_performance",
+				"webgl_shadowmap_viewer",
 				"webgl_sprites",
 				"webgl_terrain_dynamic",
 				"webgl_test_memory",
@@ -370,6 +370,9 @@
 				"webgldeferred_arealights",
 				"webgldeferred_pointlights"
 			],
+			"vr": [
+				"vr_cubes"
+			],
 			"css3d": [
 				"css3d_molecules",
 				"css3d_panorama",
@@ -385,7 +388,6 @@
 				"misc_animation_keys",
 				"misc_controls_deviceorientation",
 				"misc_controls_fly",
-				"misc_controls_oculusrift",
 				"misc_controls_orbit",
 				"misc_controls_pointerlock",
 				"misc_controls_trackball",

+ 2 - 1
examples/js/Mirror.js

@@ -110,6 +110,7 @@ THREE.Mirror = function ( renderer, camera, options ) {
 	this.textureMatrix = new THREE.Matrix4();
 
 	this.mirrorCamera = this.camera.clone();
+	this.mirrorCamera.matrixAutoUpdate = true;
 
 	this.texture = new THREE.WebGLRenderTarget( width, height );
 	this.tempTexture = new THREE.WebGLRenderTarget( width, height );
@@ -142,7 +143,7 @@ THREE.Mirror = function ( renderer, camera, options ) {
 };
 
 THREE.Mirror.prototype = Object.create( THREE.Object3D.prototype );
-THREE.Mirror.prototype.constructor = THREE.Mirror;
+THREE.Mirror.prototype.constructor = THREE.Mirror;
 
 THREE.Mirror.prototype.renderWithMirror = function ( otherMirror ) {
 

+ 4 - 3
examples/js/Ocean.js

@@ -41,6 +41,7 @@
 	this.matrixNeedsUpdate = false;
 	
 	// Setup framebuffer pipeline
+	var renderTargetType = optionalParameter(options.USE_HALF_FLOAT, false) ? THREE.HalfFloatType : THREE.FloatType;
 	var LinearClampParams = {
 		minFilter: THREE.LinearFilter,
 		magFilter: THREE.LinearFilter,
@@ -50,7 +51,7 @@
 		stencilBuffer: false,
 		depthBuffer: false,
 		premultiplyAlpha: false,
-		type: THREE.FloatType
+		type: renderTargetType
 	};
 	var NearestClampParams = {
 		minFilter: THREE.NearestFilter,
@@ -61,7 +62,7 @@
 		stencilBuffer: false,
 		depthBuffer: false,
 		premultiplyAlpha:false,
-		type: THREE.FloatType
+		type: renderTargetType
 	};
 	var NearestRepeatParams = {
 		minFilter: THREE.NearestFilter,
@@ -72,7 +73,7 @@
 		stencilBuffer: false,
 		depthBuffer: false,
 		premultiplyAlpha: false,
-		type: THREE.FloatType
+		type: renderTargetType
 	};
 	this.initialSpectrumFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestRepeatParams);
 	this.spectrumFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestClampParams);

+ 3 - 5
examples/js/ShaderDeferred.js

@@ -147,6 +147,7 @@ THREE.ShaderDeferred = {
 			"uniform float wrapAround;",
 			"uniform float additiveSpecular;",
 
+			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "color_pars_fragment" ],
 			THREE.ShaderChunk[ "map_pars_fragment" ],
 			THREE.ShaderChunk[ "lightmap_pars_fragment" ],
@@ -225,11 +226,7 @@ THREE.ShaderDeferred = {
 
 					"#endif",
 
-					"#ifdef GAMMA_INPUT",
-
-						"cubeColor.xyz *= cubeColor.xyz;",
-
-					"#endif",
+					"cubeColor.xyz = inputToLinear( cubeColor.xyz );",
 
 					"if ( combine == 1 ) {",
 
@@ -308,6 +305,7 @@ THREE.ShaderDeferred = {
 
 		vertexShader : [
 
+			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "map_pars_vertex" ],
 			THREE.ShaderChunk[ "lightmap_pars_vertex" ],
 			THREE.ShaderChunk[ "color_pars_vertex" ],

+ 26 - 35
examples/js/ShaderSkin.js

@@ -38,7 +38,6 @@ THREE.ShaderSkin = {
 
 			"diffuse":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
 			"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
-			"ambient":  { type: "c", value: new THREE.Color( 0x050505 ) },
 			"opacity": 	  { type: "f", value: 1 },
 
 			"uRoughness": 	  		{ type: "f", value: 0.15 },
@@ -65,7 +64,6 @@ THREE.ShaderSkin = {
 			"uniform bool enableBump;",
 			"uniform bool enableSpecular;",
 
-			"uniform vec3 ambient;",
 			"uniform vec3 diffuse;",
 			"uniform vec3 specular;",
 			"uniform float opacity;",
@@ -105,11 +103,13 @@ THREE.ShaderSkin = {
 				"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
 
 			"#endif",
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
 			THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
@@ -202,10 +202,7 @@ THREE.ShaderSkin = {
 
 						"vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
 
-						"float lDistance = 1.0;",
-
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
 						"lVector = normalize( lVector );",
 
@@ -215,8 +212,8 @@ THREE.ShaderSkin = {
 
 						"float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewPosition, uRoughness, uSpecularBrightness );",
 
-						"totalDiffuseLight    += lDistance * pointLightColor[ i ] * pointDiffuseWeight;",
-						"totalSpecularLight += lDistance * specular * pointLightColor[ i ] * pointSpecularWeight * specularStrength;",
+						"totalDiffuseLight    += attenuation * pointLightColor[ i ] * pointDiffuseWeight;",
+						"totalSpecularLight += attenuation * specular * pointLightColor[ i ] * pointSpecularWeight * specularStrength;",
 
 					"}",
 
@@ -228,9 +225,7 @@ THREE.ShaderSkin = {
 
 					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
-						"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
-
-						"vec3 dirVector = normalize( lDirection.xyz );",
+						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
 
 						"float dirDiffuseWeightFull = max( dot( normal, dirVector ), 0.0 );",
 						"float dirDiffuseWeightHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
@@ -251,8 +246,7 @@ THREE.ShaderSkin = {
 
 					"for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
 
-						"vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
-						"vec3 lVector = normalize( lDirection.xyz );",
+						"vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );",
 
 						"float dotProduct = dot( normal, lVector );",
 						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
@@ -275,7 +269,7 @@ THREE.ShaderSkin = {
 
 				"#endif",
 
-				"outgoingLight.xyz += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor * ambient ) + totalSpecularLight;",
+				"outgoingLight.xyz += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor * diffuse ) + totalSpecularLight;",
 
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
@@ -297,6 +291,7 @@ THREE.ShaderSkin = {
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
 
 			"void main() {",
@@ -360,7 +355,6 @@ THREE.ShaderSkin = {
 
 			"diffuse":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
 			"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
-			"ambient":  { type: "c", value: new THREE.Color( 0x050505 ) },
 			"opacity": 	  { type: "f", value: 1 },
 
 			"uRoughness": 	  		{ type: "f", value: 0.15 },
@@ -372,7 +366,6 @@ THREE.ShaderSkin = {
 
 		fragmentShader: [
 
-			"uniform vec3 ambient;",
 			"uniform vec3 diffuse;",
 			"uniform vec3 specular;",
 			"uniform float opacity;",
@@ -413,6 +406,7 @@ THREE.ShaderSkin = {
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
 
 			"float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
@@ -503,12 +497,10 @@ THREE.ShaderSkin = {
 				// directional lights
 
 				"#if MAX_DIR_LIGHTS > 0",
-			
-					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
-						"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
+					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
-						"vec3 dirVector = normalize( lDirection.xyz );",
+						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
 
 						"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
 
@@ -534,11 +526,11 @@ THREE.ShaderSkin = {
 
 					"#ifdef VERSION1",
 
-						"vec3 nonblurColor = sqrt( gl_FragColor.xyz );",
+						"vec3 nonblurColor = sqrt(outgoingLight.xyz );",
 
 					"#else",
 
-						"vec3 nonblurColor = gl_FragColor.xyz;",
+						"vec3 nonblurColor = outgoingLight.xyz;",
 
 					"#endif",
 
@@ -555,14 +547,13 @@ THREE.ShaderSkin = {
 					//"gl_FragColor = vec4( vec3( 0.25, 0.6, 0.8 ) * nonblurColor + vec3( 0.15, 0.25, 0.2 ) * blur1Color + vec3( 0.15, 0.15, 0.0 ) * blur2Color + vec3( 0.45, 0.0, 0.0 ) * blur3Color, gl_FragColor.w );",
 
 
-					"vec3 blurColor = vec3( vec3( 0.22,  0.437, 0.635 ) * nonblurColor + ",
+					"outgoingLight += vec3( vec3( 0.22,  0.437, 0.635 ) * nonblurColor + ",
 										 "vec3( 0.101, 0.355, 0.365 ) * blur1Color + ",
 										 "vec3( 0.119, 0.208, 0.0 )   * blur2Color + ",
 										 "vec3( 0.114, 0.0,   0.0 )   * blur3Color + ",
 										 "vec3( 0.444, 0.0,   0.0 )   * blur4Color );",
 
-
-					"outgoingLight += ambientLightColor * sqrt( diffuseColor.rgb ) * blurColor + totalSpecularLight;",
+					"outgoingLight += ambientLightColor * diffuse + totalSpecularLight;",
 
 					"#ifndef VERSION1",
 
@@ -601,6 +592,7 @@ THREE.ShaderSkin = {
 
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
 
 				"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
 
@@ -608,6 +600,8 @@ THREE.ShaderSkin = {
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
+
 			"void main() {",
 
 				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
@@ -637,14 +631,11 @@ THREE.ShaderSkin = {
 
 						"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
 
-						"float lDistance = 1.0;",
-
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
 						"lVector = normalize( lVector );",
 
-						"vPointLight[ i ] = vec4( lVector, lDistance );",
+						"vPointLight[ i ] = vec4( lVector, attenuation );",
 
 					"}",
 
@@ -690,6 +681,7 @@ THREE.ShaderSkin = {
 
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
 
 				"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
 
@@ -697,6 +689,8 @@ THREE.ShaderSkin = {
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
+
 			"void main() {",
 
 				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
@@ -726,14 +720,11 @@ THREE.ShaderSkin = {
 
 						"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
 
-						"float lDistance = 1.0;",
-
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
 						"lVector = normalize( lVector );",
 
-						"vPointLight[ i ] = vec4( lVector, lDistance );",
+						"vPointLight[ i ] = vec4( lVector, attenuation );",
 
 					"}",
 

+ 10 - 21
examples/js/ShaderTerrain.js

@@ -42,7 +42,6 @@ THREE.ShaderTerrain = {
 
 			"diffuse": { type: "c", value: new THREE.Color( 0xeeeeee ) },
 			"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
-			"ambient": { type: "c", value: new THREE.Color( 0x050505 ) },
 			"shininess": { type: "f", value: 30 },
 			"opacity": { type: "f", value: 1 },
 
@@ -57,7 +56,6 @@ THREE.ShaderTerrain = {
 
 		fragmentShader: [
 
-			"uniform vec3 ambient;",
 			"uniform vec3 diffuse;",
 			"uniform vec3 specular;",
 			"uniform float shininess;",
@@ -108,11 +106,13 @@ THREE.ShaderTerrain = {
 				"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+				"uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
 
 			"#endif",
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
 
@@ -135,12 +135,8 @@ THREE.ShaderTerrain = {
 					"vec4 colDiffuse1 = texture2D( tDiffuse1, uvOverlay );",
 					"vec4 colDiffuse2 = texture2D( tDiffuse2, uvOverlay );",
 
-					"#ifdef GAMMA_INPUT",
-
-						"colDiffuse1.xyz *= colDiffuse1.xyz;",
-						"colDiffuse2.xyz *= colDiffuse2.xyz;",
-
-					"#endif",
+					"colDiffuse1.xyz = inputToLinear( colDiffuse1.xyz );",
+					"colDiffuse2.xyz = inputToLinear( colDiffuse2.xyz );",
 
 					"diffuseColor *= mix ( colDiffuse1, colDiffuse2, 1.0 - texture2D( tDisplacement, uvBase ) );",
 
@@ -175,22 +171,19 @@ THREE.ShaderTerrain = {
 						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 						"vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
 
-						"float lDistance = 1.0;",
-						"if ( pointLightDistance[ i ] > 0.0 )",
-							"lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
 						"lVector = normalize( lVector );",
 
 						"vec3 pointHalfVector = normalize( lVector + viewPosition );",
-						"float pointDistance = lDistance;",
 
 						"float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
 						"float pointDiffuseWeight = max( dot( normal, lVector ), 0.0 );",
 
 						"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
 
-						"totalDiffuseLight += pointDistance * pointLightColor[ i ] * pointDiffuseWeight;",
-						"totalSpecularLight += pointDistance * pointLightColor[ i ] * specular * pointSpecularWeight * pointDiffuseWeight;",
+						"totalDiffuseLight += attenuation * pointLightColor[ i ] * pointDiffuseWeight;",
+						"totalSpecularLight += attenuation * pointLightColor[ i ] * specular * pointSpecularWeight * pointDiffuseWeight;",
 
 					"}",
 
@@ -205,9 +198,7 @@ THREE.ShaderTerrain = {
 
 					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
-						"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
-
-						"vec3 dirVector = normalize( lDirection.xyz );",
+						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
 						"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
 
 						"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
@@ -231,8 +222,7 @@ THREE.ShaderTerrain = {
 
 					"for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
 
-						"vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
-						"vec3 lVector = normalize( lDirection.xyz );",
+						"vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );",
 
 						// diffuse
 
@@ -263,8 +253,7 @@ THREE.ShaderTerrain = {
 
 				"#endif",
 
-				//"gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * ambient) + totalSpecular;",
-				"outgoingLight.rgb += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor * ambient + totalSpecularLight );",
+				"outgoingLight.rgb += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor * diffuse + totalSpecularLight );",
 
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],

+ 0 - 4
examples/js/controls/EditorControls.js

@@ -116,8 +116,6 @@ THREE.EditorControls = function ( object, domElement ) {
 
 		if ( scope.enabled === false ) return;
 
-		event.preventDefault();
-
 		if ( event.button === 0 ) {
 
 			state = STATE.ROTATE;
@@ -145,8 +143,6 @@ THREE.EditorControls = function ( object, domElement ) {
 
 		if ( scope.enabled === false ) return;
 
-		event.preventDefault();
-
 		pointer.set( event.clientX, event.clientY );
 
 		var movementX = pointer.x - pointerOld.x;

+ 0 - 61
examples/js/controls/OculusControls.js

@@ -1,61 +0,0 @@
-/**
- * @author possan / http://possan.se/
- *
- * Oculus headtracking control
- * - use together with the oculus-rest project to get headtracking
- *   coordinates from the rift: http://github.com/possan/oculus-rest
- */
-
-THREE.OculusControls = function ( object ) {
-
-	this.object = object;
-	this.target = new THREE.Vector3( 0, 0, 0 );
-
-	this.enabled = true;
-	this.headquat = new THREE.Quaternion();
-
-	this.loadAjaxJSON = function ( url, callback ) {
-		var xhr = new XMLHttpRequest();
-		xhr.onreadystatechange = function () {
-			if ( xhr.readyState === xhr.DONE ) {
-				if ( xhr.status === 200 || xhr.status === 0 ) {
-					if ( xhr.responseText ) {
-						var json = JSON.parse( xhr.responseText );
-						callback( json );
-					}
-				}
-			}
-		};
-		xhr.open( "GET", url, true );
-		xhr.withCredentials = false;
-		xhr.send( null );
-	};
-
-	this.gotCoordinates = function( r ) {
-		this.headquat.set(r.quat.x, r.quat.y, r.quat.z, r.quat.w);
-		this.queuePoll();
-	}
-
-	this.pollOnce = function() {
-		this.loadAjaxJSON('http://localhost:50000', bind(this, this.gotCoordinates));
-	}
-
-	this.queuePoll = function() {
-		setTimeout(bind(this, this.pollOnce), 10);
-	}
-
-	this.update = function( delta ) {
-		if ( this.enabled === false ) return;
-		this.object.quaternion.multiply(this.headquat);
-	};
-
-	function bind( scope, fn ) {
-		return function () {
-			fn.apply( scope, arguments );
-		};
-	};
-
-	this.connect = function() {
-		this.queuePoll();
-	};
-};

+ 0 - 6
examples/js/controls/OrbitControls.js

@@ -14,12 +14,6 @@
 //    Orbit - left mouse / touch: one finger move
 //    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
 //    Pan - right mouse, or arrow keys / touch: three finter swipe
-//
-// This is a drop-in replacement for (most) TrackballControls used in examples.
-// That is, include this js file and wherever you see:
-//    	controls = new THREE.TrackballControls( camera );
-//      controls.target.z = 150;
-// Simple substitute "OrbitControls" and the control should work as-is.
 
 THREE.OrbitControls = function ( object, domElement ) {
 

+ 194 - 105
examples/js/controls/OrthographicTrackballControls.js

@@ -1,12 +1,14 @@
 /**
  * @author Eberhard Graether / http://egraether.com/
+ * @author Mark Lundin 	/ http://mark-lundin.com
  * @author Patrick Fuller / http://patrick-fuller.com
+ * @author Max Smolens / https://github.com/msmolens
  */
 
 THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	var _this = this;
-	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM: 4, TOUCH_PAN: 5 };
+	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
 
 	this.object = object;
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
@@ -15,16 +17,17 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	this.enabled = true;
 
-	this.screen = { width: 0, height: 0, offsetLeft: 0, offsetTop: 0 };
-	this.radius = ( this.screen.width + this.screen.height ) / 4;
+	this.screen = { left: 0, top: 0, width: 0, height: 0 };
+
+	this.radius = 0;
 
 	this.rotateSpeed = 1.0;
 	this.zoomSpeed = 1.2;
-	this.panSpeed = 0.3;
 
 	this.noRotate = false;
 	this.noZoom = false;
 	this.noPan = false;
+	this.noRoll = false;
 
 	this.staticMoving = false;
 	this.dynamicDampingFactor = 0.2;
@@ -35,7 +38,9 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	this.target = new THREE.Vector3();
 
-	var lastPosition = new THREE.Vector3();
+	var EPS = 0.000001;
+
+	var _changed = true;
 
 	var _state = STATE.NONE,
 	_prevState = STATE.NONE,
@@ -47,7 +52,6 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	_zoomStart = new THREE.Vector2(),
 	_zoomEnd = new THREE.Vector2(),
-	_zoomFactor = 1,
 
 	_touchZoomDistanceStart = 0,
 	_touchZoomDistanceEnd = 0,
@@ -65,24 +69,43 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 	this.right0 = this.object.right;
 	this.top0 = this.object.top;
 	this.bottom0 = this.object.bottom;
-	this.center0 = new THREE.Vector2((this.left0 + this.right0) / 2.0, (this.top0 + this.bottom0) / 2.0);
 
 	// events
 
 	var changeEvent = { type: 'change' };
+	var startEvent = { type: 'start'};
+	var endEvent = { type: 'end'};
 
 
 	// methods
 
 	this.handleResize = function () {
 
-		this.screen.width = window.innerWidth;
-		this.screen.height = window.innerHeight;
+		if ( this.domElement === document ) {
+
+			this.screen.left = 0;
+			this.screen.top = 0;
+			this.screen.width = window.innerWidth;
+			this.screen.height = window.innerHeight;
+
+		} else {
+
+			var box = this.domElement.getBoundingClientRect();
+			// adjustments come from similar code in the jquery offset() function
+			var d = this.domElement.ownerDocument.documentElement;
+			this.screen.left = box.left + window.pageXOffset - d.clientLeft;
+			this.screen.top = box.top + window.pageYOffset - d.clientTop;
+			this.screen.width = box.width;
+			this.screen.height = box.height;
+
+		}
 
-		this.screen.offsetLeft = 0;
-		this.screen.offsetTop = 0;
+		this.radius = 0.5 * Math.min( this.screen.width, this.screen.height );
 
-		this.radius = ( this.screen.width + this.screen.height ) / 4;
+		this.left0 = this.object.left;
+		this.right0 = this.object.right;
+		this.top0 = this.object.top;
+		this.bottom0 = this.object.bottom;
 
 	};
 
@@ -96,102 +119,132 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	};
 
-	this.getMouseOnScreen = function ( clientX, clientY ) {
+	var getMouseOnScreen = ( function () {
 
-		return new THREE.Vector2(
-			( clientX - _this.screen.offsetLeft ) / _this.radius * 0.5,
-			( clientY - _this.screen.offsetTop ) / _this.radius * 0.5
-		);
+		var vector = new THREE.Vector2();
 
-	};
+		return function ( pageX, pageY ) {
 
-	this.getMouseProjectionOnBall = function ( clientX, clientY ) {
+			vector.set(
+				( pageX - _this.screen.left ) / _this.screen.width,
+				( pageY - _this.screen.top ) / _this.screen.height
+			);
 
-		var mouseOnBall = new THREE.Vector3(
-			( clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft ) / _this.radius,
-			( _this.screen.height * 0.5 + _this.screen.offsetTop - clientY ) / _this.radius,
-			0.0
-		);
+			return vector;
 
-		var length = mouseOnBall.length();
+		};
 
-		if ( length > 1.0 ) {
+	}() );
 
-			mouseOnBall.normalize();
+	var getMouseProjectionOnBall = ( function () {
 
-		} else {
+		var vector = new THREE.Vector3();
+		var objectUp = new THREE.Vector3();
+		var mouseOnBall = new THREE.Vector3();
 
-			mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+		return function ( pageX, pageY ) {
 
-		}
+			mouseOnBall.set(
+				( pageX - _this.screen.width * 0.5 - _this.screen.left ) / _this.radius,
+				( _this.screen.height * 0.5 + _this.screen.top - pageY ) / _this.radius,
+				0.0
+			);
 
-		_eye.copy( _this.object.position ).sub( _this.target );
+			var length = mouseOnBall.length();
 
-		var projection = _this.object.up.clone().setLength( mouseOnBall.y );
-		projection.add( _this.object.up.clone().cross( _eye ).setLength( mouseOnBall.x ) );
-		projection.add( _eye.setLength( mouseOnBall.z ) );
+			if ( _this.noRoll ) {
 
-		return projection;
+				if ( length < Math.SQRT1_2 ) {
 
-	};
+					mouseOnBall.z = Math.sqrt( 1.0 - length*length );
+
+				} else {
+
+					mouseOnBall.z = .5 / length;
+
+				}
 
-	this.rotateCamera = function () {
+			} else if ( length > 1.0 ) {
 
-		var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
+				mouseOnBall.normalize();
 
-		if ( angle ) {
+			} else {
 
-			var axis = ( new THREE.Vector3() ).crossVectors( _rotateStart, _rotateEnd ).normalize(),
-				quaternion = new THREE.Quaternion();
+				mouseOnBall.z = Math.sqrt( 1.0 - length * length );
 
-			angle *= _this.rotateSpeed;
+			}
 
-			quaternion.setFromAxisAngle( axis, -angle );
+			_eye.copy( _this.object.position ).sub( _this.target );
 
-			_eye.applyQuaternion( quaternion );
-			_this.object.up.applyQuaternion( quaternion );
+			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 ) );
 
-			_rotateEnd.applyQuaternion( quaternion );
+			return vector;
 
-			if ( _this.staticMoving ) {
+		};
 
-				_rotateStart.copy( _rotateEnd );
+	}() );
 
-			} else {
+	this.rotateCamera = (function(){
 
-				quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
-				_rotateStart.applyQuaternion( quaternion );
+		var axis = new THREE.Vector3(),
+			quaternion = new THREE.Quaternion();
 
-			}
 
+		return function () {
+
+			var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
+
+			if ( angle ) {
+
+				axis.crossVectors( _rotateStart, _rotateEnd ).normalize();
+
+				angle *= _this.rotateSpeed;
+
+				quaternion.setFromAxisAngle( axis, -angle );
+
+				_eye.applyQuaternion( quaternion );
+				_this.object.up.applyQuaternion( quaternion );
+
+				_rotateEnd.applyQuaternion( quaternion );
+
+				if ( _this.staticMoving ) {
+
+					_rotateStart.copy( _rotateEnd );
+
+				} else {
+
+					quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
+					_rotateStart.applyQuaternion( quaternion );
+
+				}
+
+				_changed = true;
+
+			}
 		}
 
-	};
+	}());
 
 	this.zoomCamera = function () {
 
-		if ( _state === STATE.TOUCH_ZOOM ) {
+		if ( _state === STATE.TOUCH_ZOOM_PAN ) {
 
-			var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
+			var factor = _touchZoomDistanceEnd / _touchZoomDistanceStart;
 			_touchZoomDistanceStart = _touchZoomDistanceEnd;
-			_zoomFactor *= factor;
 
-			_this.object.left = _zoomFactor * _this.left0 + ( 1 - _zoomFactor ) *  _this.center0.x;
-			_this.object.right = _zoomFactor * _this.right0 + ( 1 - _zoomFactor ) *  _this.center0.x;
-			_this.object.top = _zoomFactor * _this.top0 + ( 1 - _zoomFactor ) *  _this.center0.y;
-			_this.object.bottom = _zoomFactor * _this.bottom0 + ( 1 - _zoomFactor ) *  _this.center0.y;
+			_this.object.zoom *= factor;
+
+			_changed = true;
 
 		} else {
 
 			var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
 
-			if ( factor !== 1.0 && factor > 0.0 ) {
-				_zoomFactor *= factor;
+			if ( Math.abs( factor - 1.0 ) > EPS && factor > 0.0 ) {
 
-				_this.object.left = _zoomFactor * _this.left0 + ( 1 - _zoomFactor ) *  _this.center0.x;
-				_this.object.right = _zoomFactor * _this.right0 + ( 1 - _zoomFactor ) *  _this.center0.x;
-				_this.object.top = _zoomFactor * _this.top0 + ( 1 - _zoomFactor ) *  _this.center0.y;
-				_this.object.bottom = _zoomFactor * _this.bottom0 + ( 1 - _zoomFactor ) *  _this.center0.y;
+				_this.object.zoom *= factor;
 
 				if ( _this.staticMoving ) {
 
@@ -203,39 +256,54 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 				}
 
+				_changed = true;
+
 			}
 
 		}
 
 	};
 
-	this.panCamera = function () {
+	this.panCamera = (function(){
 
-		var mouseChange = _panEnd.clone().sub( _panStart );
+		var mouseChange = new THREE.Vector2(),
+			objectUp = new THREE.Vector3(),
+			pan = new THREE.Vector3();
 
-		if ( mouseChange.lengthSq() ) {
+		return function () {
 
-			mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
+			mouseChange.copy( _panEnd ).sub( _panStart );
 
-			var pan = _eye.clone().cross( _this.object.up ).setLength( mouseChange.x );
-			pan.add( _this.object.up.clone().setLength( mouseChange.y ) );
+			if ( mouseChange.lengthSq() ) {
 
-			_this.object.position.add( pan );
-			_this.target.add( pan );
+				// Scale movement to keep clicked/dragged position under cursor
+				var scale_x = ( _this.object.right - _this.object.left ) / _this.object.zoom;
+				var scale_y = ( _this.object.top - _this.object.bottom ) / _this.object.zoom;
+				mouseChange.x *= scale_x;
+				mouseChange.y *= scale_y;
 
-			if ( _this.staticMoving ) {
+				pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
+				pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
 
-				_panStart = _panEnd;
+				_this.object.position.add( pan );
+				_this.target.add( pan );
 
-			} else {
+				if ( _this.staticMoving ) {
 
-				_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
+					_panStart.copy( _panEnd );
 
-			}
+				} else {
+
+					_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
 
+				}
+
+				_changed = true;
+
+			}
 		}
 
-	};
+	}());
 
 	this.update = function () {
 
@@ -250,7 +318,12 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 		if ( !_this.noZoom ) {
 
 			_this.zoomCamera();
-			_this.object.updateProjectionMatrix();
+
+			if ( _changed ) {
+
+				_this.object.updateProjectionMatrix();
+
+			}
 
 		}
 
@@ -264,11 +337,11 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		_this.object.lookAt( _this.target );
 
-		if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ) {
+		if ( _changed ) {
 
 			_this.dispatchEvent( changeEvent );
 
-			lastPosition.copy( _this.object.position );
+			_changed = false;
 
 		}
 
@@ -294,7 +367,7 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		_this.dispatchEvent( changeEvent );
 
-		lastPosition.copy( _this.object.position );
+		_changed = false;
 
 	};
 
@@ -353,21 +426,26 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 
-			_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
+			_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
+			_rotateEnd.copy( _rotateStart );
 
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 
-			_zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_zoomEnd.copy(_zoomStart);
 
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 
-			_panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_panEnd.copy(_panStart)
 
 		}
 
 		document.addEventListener( 'mousemove', mousemove, false );
 		document.addEventListener( 'mouseup', mouseup, false );
 
+		_this.dispatchEvent( startEvent );
+
 	}
 
 	function mousemove( event ) {
@@ -379,15 +457,15 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 
-			_rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
+			_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
 
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 
-			_zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 
-			_panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
 		}
 
@@ -404,6 +482,7 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		document.removeEventListener( 'mousemove', mousemove );
 		document.removeEventListener( 'mouseup', mouseup );
+		_this.dispatchEvent( endEvent );
 
 	}
 
@@ -427,6 +506,8 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 		}
 
 		_zoomStart.y += delta * 0.01;
+		_this.dispatchEvent( startEvent );
+		_this.dispatchEvent( endEvent );
 
 	}
 
@@ -438,25 +519,27 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 			case 1:
 				_state = STATE.TOUCH_ROTATE;
-				_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateEnd.copy( _rotateStart );
 				break;
 
 			case 2:
-				_state = STATE.TOUCH_ZOOM;
+				_state = STATE.TOUCH_ZOOM_PAN;
 				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
 				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
 				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
-				break;
 
-			case 3:
-				_state = STATE.TOUCH_PAN;
-				_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panStart.copy( getMouseOnScreen( x, y ) );
+				_panEnd.copy( _panStart );
 				break;
 
 			default:
 				_state = STATE.NONE;
 
 		}
+		_this.dispatchEvent( startEvent );
 
 	}
 
@@ -470,17 +553,17 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 
 			case 1:
-				_rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
 				break;
 
 			case 2:
 				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
 				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
-				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy )
-				break;
+				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
 
-			case 3:
-				_panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
 				break;
 
 			default:
@@ -497,20 +580,23 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 
 			case 1:
-				_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateStart.copy( _rotateEnd );
 				break;
 
 			case 2:
 				_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
-				break;
 
-			case 3:
-				_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
+				_panStart.copy( _panEnd );
 				break;
 
 		}
 
 		_state = STATE.NONE;
+		_this.dispatchEvent( endEvent );
 
 	}
 
@@ -530,6 +616,9 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	this.handleResize();
 
+	// force an update at start
+	this.update();
+
 };
 
 THREE.OrthographicTrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );

+ 10 - 10
examples/js/controls/TransformControls.js

@@ -97,7 +97,7 @@
 
 			//// PLANES
 
-			var planeGeometry = new THREE.PlaneGeometry( 50, 50, 2, 2 );
+			var planeGeometry = new THREE.PlaneBufferGeometry( 50, 50, 2, 2 );
 			var planeMaterial = new THREE.MeshBasicMaterial( { wireframe: true } );
 			planeMaterial.side = THREE.DoubleSide;
 
@@ -154,10 +154,10 @@
 				if (child instanceof THREE.Mesh) {
 					child.updateMatrix();
 
-					var tempGeometry = new THREE.Geometry();
-					tempGeometry.merge( child.geometry, child.matrix );
-
+					var tempGeometry = child.geometry.clone();
+					tempGeometry.applyMatrix( child.matrix );
 					child.geometry = tempGeometry;
+
 					child.position.set( 0, 0, 0 );
 					child.rotation.set( 0, 0, 0 );
 					child.scale.set( 1, 1, 1 );
@@ -251,13 +251,13 @@
 				[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), new GizmoMaterial( { color: 0xffffff, opacity: 0.25 } ) ), [ 0, 0, 0 ], [ 0, 0, 0 ] ]
 			],
 			XY: [
-				[ new THREE.Mesh( new THREE.PlaneGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) ), [ 0.15, 0.15, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) ), [ 0.15, 0.15, 0 ] ]
 			],
 			YZ: [
-				[ new THREE.Mesh( new THREE.PlaneGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0x00ffff, opacity: 0.25 } ) ), [ 0, 0.15, 0.15 ], [ 0, Math.PI/2, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0x00ffff, opacity: 0.25 } ) ), [ 0, 0.15, 0.15 ], [ 0, Math.PI/2, 0 ] ]
 			],
 			XZ: [
-				[ new THREE.Mesh( new THREE.PlaneGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ), [ 0.15, 0, 0.15 ], [ -Math.PI/2, 0, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ), [ 0.15, 0, 0.15 ], [ -Math.PI/2, 0, 0 ] ]
 			]
 		};
 
@@ -275,13 +275,13 @@
 				[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.2, 0 ), new GizmoMaterial( { color: 0xffffff, opacity: 0.25 } ) ) ]
 			],
 			XY: [
-				[ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), new GizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) ), [ 0.2, 0.2, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), new GizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) ), [ 0.2, 0.2, 0 ] ]
 			],
 			YZ: [
-				[ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), new GizmoMaterial( { color: 0x00ffff, opacity: 0.25 } ) ), [ 0, 0.2, 0.2 ], [ 0, Math.PI/2, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), new GizmoMaterial( { color: 0x00ffff, opacity: 0.25 } ) ), [ 0, 0.2, 0.2 ], [ 0, Math.PI/2, 0 ] ]
 			],
 			XZ: [
-				[ new THREE.Mesh( new THREE.PlaneGeometry( 0.4, 0.4 ), new GizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ), [ 0.2, 0, 0.2 ], [ -Math.PI/2, 0, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), new GizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ), [ 0.2, 0, 0.2 ], [ -Math.PI/2, 0, 0 ] ]
 			]
 		};
 

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно