Mr.doob 1 year ago
parent
commit
de2a2da880
100 changed files with 1029 additions and 1362 deletions
  1. 144 236
      build/three.cjs
  2. 144 236
      build/three.module.js
  3. 0 0
      build/three.module.min.js
  4. 5 1
      docs/api/ar/constants/Renderer.html
  5. 45 39
      docs/api/ar/core/Raycaster.html
  6. 0 1
      docs/api/ar/core/bufferAttributeTypes/BufferAttributeTypes.html
  7. 1 1
      docs/api/ar/helpers/GridHelper.html
  8. 1 1
      docs/api/ar/helpers/PolarGridHelper.html
  9. 0 75
      docs/api/ar/renderers/WebGLMultipleRenderTargets.html
  10. 7 4
      docs/api/en/constants/Renderer.html
  11. 6 8
      docs/api/en/core/BufferGeometry.html
  12. 22 0
      docs/api/en/core/Object3D.html
  13. 10 4
      docs/api/en/core/Raycaster.html
  14. 0 1
      docs/api/en/core/bufferAttributeTypes/BufferAttributeTypes.html
  15. 1 1
      docs/api/en/helpers/GridHelper.html
  16. 1 1
      docs/api/en/helpers/PolarGridHelper.html
  17. 5 0
      docs/api/en/materials/MeshBasicMaterial.html
  18. 5 0
      docs/api/en/materials/MeshLambertMaterial.html
  19. 5 0
      docs/api/en/materials/MeshPhongMaterial.html
  20. 30 0
      docs/api/en/materials/MeshPhysicalMaterial.html
  21. 5 0
      docs/api/en/materials/MeshStandardMaterial.html
  22. 42 7
      docs/api/en/objects/InstancedMesh.html
  23. 6 10
      docs/api/en/objects/SkinnedMesh.html
  24. 0 75
      docs/api/en/renderers/WebGLMultipleRenderTargets.html
  25. 8 1
      docs/api/en/renderers/WebGLRenderTarget.html
  26. 12 0
      docs/api/en/scenes/Scene.html
  27. 5 2
      docs/api/fr/constants/Renderer.html
  28. 5 1
      docs/api/it/constants/Renderer.html
  29. 13 7
      docs/api/it/core/Raycaster.html
  30. 0 1
      docs/api/it/core/bufferAttributeTypes/BufferAttributeTypes.html
  31. 1 1
      docs/api/it/helpers/GridHelper.html
  32. 1 1
      docs/api/it/helpers/PolarGridHelper.html
  33. 0 67
      docs/api/it/renderers/WebGLMultipleRenderTargets.html
  34. 8 1
      docs/api/it/renderers/WebGLRenderTarget.html
  35. 4 1
      docs/api/ko/constants/Renderer.html
  36. 6 0
      docs/api/ko/core/Raycaster.html
  37. 0 1
      docs/api/ko/core/bufferAttributeTypes/BufferAttributeTypes.html
  38. 5 1
      docs/api/pt-br/constants/Renderer.html
  39. 4 0
      docs/api/zh/constants/CustomBlendingEquations.html
  40. 4 1
      docs/api/zh/constants/Renderer.html
  41. 6 0
      docs/api/zh/core/Raycaster.html
  42. 0 1
      docs/api/zh/core/bufferAttributeTypes/BufferAttributeTypes.html
  43. 1 1
      docs/api/zh/helpers/GridHelper.html
  44. 1 1
      docs/api/zh/helpers/PolarGridHelper.html
  45. 12 5
      docs/api/zh/materials/Material.html
  46. 0 61
      docs/api/zh/renderers/WebGLMultipleRenderTargets.html
  47. 8 1
      docs/api/zh/renderers/WebGLRenderTarget.html
  48. 15 0
      docs/examples/en/controls/DragControls.html
  49. 6 6
      docs/examples/en/loaders/3DMLoader.html
  50. 3 3
      docs/examples/en/loaders/GLTFLoader.html
  51. 10 0
      docs/examples/ko/controls/DragControls.html
  52. 2 3
      docs/examples/zh/animations/CCDIKSolver.html
  53. 2 3
      docs/examples/zh/animations/MMDAnimationHelper.html
  54. 2 3
      docs/examples/zh/animations/MMDPhysics.html
  55. 2 3
      docs/examples/zh/controls/ArcballControls.html
  56. 10 0
      docs/examples/zh/controls/DragControls.html
  57. 2 3
      docs/examples/zh/controls/MapControls.html
  58. 2 3
      docs/examples/zh/exporters/DRACOExporter.html
  59. 2 3
      docs/examples/zh/exporters/EXRExporter.html
  60. 2 3
      docs/examples/zh/exporters/GLTFExporter.html
  61. 2 3
      docs/examples/zh/exporters/OBJExporter.html
  62. 2 3
      docs/examples/zh/exporters/PLYExporter.html
  63. 2 3
      docs/examples/zh/exporters/STLExporter.html
  64. 2 3
      docs/examples/zh/geometries/SDFGeometryGenerator.html
  65. 2 3
      docs/examples/zh/helpers/VertexTangentsHelper.html
  66. 2 3
      docs/examples/zh/loaders/3DMLoader.html
  67. 4 14
      docs/examples/zh/loaders/GLTFLoader.html
  68. 2 3
      docs/examples/zh/loaders/KTX2Loader.html
  69. 2 3
      docs/examples/zh/loaders/LDrawLoader.html
  70. 2 3
      docs/examples/zh/loaders/PDBLoader.html
  71. 2 3
      docs/examples/zh/math/MeshSurfaceSampler.html
  72. 2 3
      docs/examples/zh/math/convexhull/ConvexHull.html
  73. 2 3
      docs/examples/zh/math/convexhull/Face.html
  74. 2 3
      docs/examples/zh/math/convexhull/HalfEdge.html
  75. 2 3
      docs/examples/zh/math/convexhull/VertexList.html
  76. 2 3
      docs/examples/zh/math/convexhull/VertexNode.html
  77. 2 3
      docs/examples/zh/utils/CameraUtils.html
  78. 2 3
      docs/examples/zh/webxr/XREstimatedLight.html
  79. 0 5
      docs/list.json
  80. 30 1
      docs/manual/en/introduction/How-to-update-things.html
  81. 3 0
      docs/manual/en/introduction/Matrix-transformations.html
  82. 15 9
      editor/css/main.css
  83. 2 4
      editor/index.html
  84. 43 6
      editor/js/Editor.js
  85. 125 44
      editor/js/EditorControls.js
  86. 1 18
      editor/js/Menubar.Edit.js
  87. 3 224
      editor/js/Menubar.File.js
  88. 0 39
      editor/js/Menubar.Play.js
  89. 42 12
      editor/js/Menubar.View.js
  90. 0 2
      editor/js/Menubar.js
  91. 35 0
      editor/js/Selector.js
  92. 9 9
      editor/js/Sidebar.Geometry.BoxGeometry.js
  93. 3 3
      editor/js/Sidebar.Geometry.BufferGeometry.js
  94. 4 4
      editor/js/Sidebar.Geometry.CapsuleGeometry.js
  95. 4 4
      editor/js/Sidebar.Geometry.CircleGeometry.js
  96. 6 6
      editor/js/Sidebar.Geometry.CylinderGeometry.js
  97. 2 2
      editor/js/Sidebar.Geometry.DodecahedronGeometry.js
  98. 9 9
      editor/js/Sidebar.Geometry.ExtrudeGeometry.js
  99. 2 2
      editor/js/Sidebar.Geometry.IcosahedronGeometry.js
  100. 4 4
      editor/js/Sidebar.Geometry.LatheGeometry.js

File diff suppressed because it is too large
+ 144 - 236
build/three.cjs


File diff suppressed because it is too large
+ 144 - 236
build/three.module.js


File diff suppressed because it is too large
+ 0 - 0
build/three.module.min.js


+ 5 - 1
docs/api/ar/constants/Renderer.html

@@ -51,13 +51,17 @@
 		THREE.CineonToneMapping 
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
+		THREE.NeutralToneMapping
 		THREE.CustomToneMapping
 		</code>
 		<p>
 			هذه الخيارات تحدد خاصية [page:WebGLRenderer.toneMapping toneMapping] في WebGLRenderer. يتم استخدام هذا لتقريب مظهر نطاق الإضاءة العالي (HDR) على الوسط الذي يحتوي على نطاق إضاءة منخفض على شاشة الكمبيوتر القياسية أو شاشة الجوال.
 		</p>
 		<p>
-			THREE.LinearToneMapping، THREE.ReinhardToneMapping، THREE.CineonToneMapping، THREE.ACESFilmicToneMapping و THREE.AgXToneMapping هي تنفيذات مدمجة لتقريب مظهر نطاق الإضاءة العالي (HDR). يتوقع THREE.CustomToneMapping تنفيذًا مخصصًا عن طريق تعديل شفرة GLSL لبرنامج تظليل مقطع المواد. راجع [example:webgl_tonemapping WebGL / tonemapping] مثالًا. 
+			THREE.LinearToneMapping، THREE.ReinhardToneMapping، THREE.CineonToneMapping، THREE.ACESFilmicToneMapping، THREE.AgXToneMapping و THREE.NeutralToneMapping هي تنفيذات مدمجة لتقريب مظهر نطاق الإضاءة العالي (HDR). يتوقع THREE.CustomToneMapping تنفيذًا مخصصًا عن طريق تعديل شفرة GLSL لبرنامج تظليل مقطع المواد. راجع [example:webgl_tonemapping WebGL / tonemapping] مثالًا. 
+		</p>
+		<p>
+			THREE.NeutralToneMapping is an implementation based on the Khronos 3D Commerce Group standard tone mapping.
 		</p>
 
 		<h2>المصدر (Source)</h2>

+ 45 - 39
docs/api/ar/core/Raycaster.html

@@ -8,55 +8,55 @@
 	</head>
 	<body class="rtl">
 		<h1>[name]</h1>
-	 
+
 		<p class="desc">
 			تم تصميم هذه الفئة للمساعدة في
 			[link:https://en.wikipedia.org/wiki/Ray_casting raycasting]. يتم استخدام Raycasting
 			لاختيار الماوس (العمل على معرفة الكائنات في المساحة ثلاثية الأبعاد التي يكون عليها الماوس
 			فوق) من بين أشياء أخرى.
 		</p>
-	 
+
 		<h2>مثال الكود</h2>
 		<code>
 		const raycaster = new THREE.Raycaster();
 		const pointer = new THREE.Vector2();
-	 
+
 		function onPointerMove( event ) {
-	 
+
 		// حساب موضع المؤشر في إحداثيات الجهاز المعتدلة
 		// (-1 إلى +1) لكلا المكونين
-	 
+
 		pointer.x = ( event.clientX / window.innerWidth ) * 2 - 1;
 		pointer.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
-	 
+
 		}
-	 
+
 		function render() {
-	 
+
 		// تحديث شعاع التقاط مع الكاميرا وموضع المؤشر
 		raycaster.setFromCamera( pointer, camera );
-	 
+
 		// حساب الكائنات المتقاطعة مع شعاع التقاط
 		const intersects = raycaster.intersectObjects( scene.children );
-	 
+
 		for ( let i = 0; i < intersects.length; i ++ ) {
-	 
+
 		intersects[ i ].object.material.color.set( 0xff0000 );
-	 
+
 		}
-	 
+
 		renderer.render( scene, camera );
-	 
+
 		}
-	 
+
 		window.addEventListener( 'pointermove', onPointerMove );
-	 
+
 		window.requestAnimationFrame(render);
-	 
+
 		</code>
-	 
+
 		<h2>أمثلة (Examples)</h2>
-	 
+
 		<p>
 			[example:webgl_interactive_cubes Raycasting to a Mesh]<br />
 			[example:webgl_interactive_cubes_ortho Raycasting to a Mesh in using an OrthographicCamera]<br />
@@ -68,9 +68,9 @@
 			[example:webgl_interactive_voxelpainter Raycasting to paint voxels]<br />
 			[example:webgl_raycaster_texture Raycast to a Texture]
 		</p>
-	 
+
 		<h2>المنشئ (Constructor)</h2>
-	 
+
 		<h3>[name]( [param:Vector3 origin], [param:Vector3 direction], [param:Float near], [param:Float far] )</h3>
 		<p>
 			[page:Vector3 origin] — متجه المنشأ الذي يلقي منه الشعاع.<br />
@@ -82,64 +82,64 @@
 			أقل من قريب. القيمة الافتراضية هي Infinity.
 		</p>
 		<p>هذا يخلق كائن raycaster جديد.<br /></p>
-		 
+
 		<h2>الخصائص (Properties)</h2>
-		 
+
 		<h3>[property:Float far]</h3>
 		<p>
 			عامل بعيد للraycaster. هذه القيمة تشير إلى الكائنات التي يمكن
 			تجاهلها بناءً على المسافة. هذه القيمة لا يجب أن تكون سلبية و
 			يجب أن تكون أكبر من خاصية قريب.
 		</p>
-		 
+
 		<h3>[property:Float near]</h3>
 		<p>
 			عامل قريب للraycaster. هذه القيمة تشير إلى الكائنات التي يمكن
 			تجاهلها بناءً على المسافة. هذه القيمة لا يجب أن تكون سلبية و
 			يجب أن تكون أصغر من خاصية بعيد.
 		</p>
-		 
+
 		<h3>[property:Camera camera]</h3>
 		<p>
 			الكاميرا المستخدمة عند التصوير بالأشعة ضد كائنات تعتمد على المشهد مثل
 			كائنات billboarded مثل [page:Sprites]. يمكن تعيين هذا الحقل يدويًا أو
 			يتم تعيينه عند استدعاء "setFromCamera". افتراضات إلى null.
 		</p>
-		 
+
 		<h3>[property:Layers layers]</h3>
 		<p>
 			يستخدم من قبل [name] لتجاهل كائنات 3D بشكل اختياري عند إجراء
 			اختبارات التقاطع. يضمن المثال التالي للكود أن كائنات 3D فقط على طبقة `1` ستحظى باحترام من قِبَل المثيل من [name].
-		 
+
 			<code>
-			raycaster.layers.set( 1 ); 
-			object.layers.enable( 1 ); 
+			raycaster.layers.set( 1 );
+			object.layers.enable( 1 );
 			</code>
 		</p>
-		 
+
 		<h3>[property:Object params]</h3>
 		<p>
 			 كائن به الخصائص التالية:
-		 
+
 			<code>
-			{ 
+			{
 			Mesh: {},
 			Line: { threshold: 1 },
 			LOD: {},
 			Points: { threshold: 1 },
-			Sprite: {} 
+			Sprite: {}
 			}
 			</code>
-		 
+
 			حيث threshold هو دقة raycaster عند التقاط
 			كائنات، في وحدات العالم.
 		</p>
 
 		<h3>[property:Ray ray]</h3>
 		<p>ال[Page:Ray] المستخدم للتصوير بالأشعة.</p>
-		 
+
 		<h2>الوظائف (Methods)</h2>
-		 
+
 		<h3>[method:undefined set]( [param:Vector3 origin], [param:Vector3 direction])</h3>
 		<p>
 			[page:Vector3 origin] — متجه المنشأ الذي يلقي منه الشعاع.<br />
@@ -150,7 +150,7 @@
 			يحدث الشعاع بمنشأ واتجاه جديد. يرجى ملاحظة أن هذا
 			الطريقة تنسخ فقط القيم من الوسائط.
 		</p>
-		 
+
 		<h3>[method:undefined setFromCamera]( [param:Vector2 coords], [param:Camera camera] )</h3>
 		<p>
 			[page:Vector2 coords] — إحداثيات 2D للماوس، في تعديل جهاز
@@ -158,7 +158,13 @@
 			[page:Camera camera] — الكاميرا التي يجب أن ينبثق منها الشعاع
 		</p>
 		<p>يحدث الشعاع بمنشأ واتجاه جديد.</p>
-		 
+
+		<h3>[method:this setFromXRController]( [param:WebXRController controller] )</h3>
+		<p>
+			[page:WebXRController controller] — The controller to copy the position and direction from.
+		</p>
+		<p>Updates the ray with a new origin and direction.</p>
+
 		<h3>[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 			[page:Object3D object] — الكائن للتحقق من التقاطع مع
@@ -203,7 +209,7 @@
 			وجوه كائن، سترغب في تعيين خصائص [page:Mesh.material material]
 			[page:Material.side side] إلى `THREE.DoubleSide`.
 		</p>
-		 
+
 		<h3>[method:Array intersectObjects]( [param:Array objects], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 			[page:Array objects] — الكائنات للتحقق من التقاطع مع

+ 0 - 1
docs/api/ar/core/bufferAttributeTypes/BufferAttributeTypes.html

@@ -17,7 +17,6 @@
 		</p>
 
 		<code>
-		THREE.Float64BufferAttribute 
 		THREE.Float32BufferAttribute
 		THREE.Float16BufferAttribute 
 		THREE.Uint32BufferAttribute

+ 1 - 1
docs/api/ar/helpers/GridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body class="rtl">
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 1 - 1
docs/api/ar/helpers/PolarGridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body class="rtl">
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 0 - 75
docs/api/ar/renderers/WebGLMultipleRenderTargets.html

@@ -1,75 +0,0 @@
-<!DOCTYPE html>
-<html lang="ar">
-	<head>
-		<meta charset="utf-8" />
-		<base href="../../../" />
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body class="rtl">
-		[page:WebGLRenderTarget] &rarr;
-
-		<h1>[name]</h1>
-
-		<p class="desc">
-		هدف عرض خاص يتيح لشادر الجزء الكتابة إلى عدة
-		قوام. هذا النهج مفيد لتقنيات العرض المتقدمة مثل
-		معالجة ما بعد الإنتاج أو العرض المؤجل. انتبه: [name] يمكن استخدامه فقط
-		مع سياق عرض WebGL 2.
-		</p>
-		 
-		<h2>أمثلة (Examples)</h2>
-		 
-		<p>
-		[example:webgl2_multiple_rendertargets webgl2 / multiple / rendertargets ]
-		</p>
-		 
-		<h2>المنشئ (Constructor)</h2>
-		 
-		<h3>
-		[name]([param:Number width], [param:Number height], [param:Number count],
-		[param:Object options])
-		</h3>
-		 
-		<p>
-		[page:Number width] - عرض هدف العرض. الافتراضي هو `1`.<br />
-		[page:Number height] - ارتفاع هدف العرض. الافتراضي هو `1`.<br />
-		[page:Number count] - عدد أهداف العرض. الافتراضي هو `1`.<br />
-		 
-		options - (كائن اختياري يحمل معلمات القوام لـ
-		قوام الهدف المُنشأ تلقائيًا وعمق المخزن/مخططات المخزن booleans. لـ
-		شرح معلمات القوام انظر [page:Texture Texture]. لـ
-		قائمة بالخيارات الصالحة ، انظر [page:WebGLRenderTarget WebGLRenderTarget]).<br /><br />
-		</p>
-		 
-		<h2>الخصائص (Properties)</h2>
-		 
-		<h3>[property:Boolean isWebGLMultipleRenderTargets]</h3>
-		<p>علامة للقراءة فقط للتحقق مما إذا كان كائنًا معينًا من نوع [name].</p>
-		 
-		<h3>[property:Array texture]</h3>
-		<p>
-		يتم استبدال خاصية القوام في [name] واستبدالها بمصفوفة.
-		تحتوي هذه المصفوفة على مراجع [page:WebGLRenderTarget.texture texture]
-		من أهداف العرض المعنية.
-		</p>
-		 
-		<p>
-		خصائص [page:WebGLRenderTarget WebGLRenderTarget] متوفرة على
-		هذه الفئة.
-		</p>
-		 
-		<h2>الطرق (Methods)</h2>
-		 
-		<p>
-		طرق [page:WebGLRenderTarget WebGLRenderTarget] متوفرة على هذه
-		فئة.
-		</p>
-
-		<h2>المصدر (Source)</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-		</p>
-	</body>
-</html>

+ 7 - 4
docs/api/en/constants/Renderer.html

@@ -53,6 +53,7 @@
 		THREE.CineonToneMapping 
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
+		THREE.NeutralToneMapping
 		THREE.CustomToneMapping
 		</code>
 		<p>
@@ -61,12 +62,14 @@
 			monitor or mobile device's screen.
 		</p>
 		<p>
-			THREE.LinearToneMapping, THREE.ReinhardToneMapping,
-			THREE.CineonToneMapping, THREE.ACESFilmicToneMapping, and THREE.AgXToneMapping are built-in
-			implementations of tone mapping. THREE.CustomToneMapping expects a custom
-			implementation by modyfing GLSL code of the material's fragment shader.
+			THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping, 
+			THREE.AgXToneMapping and THREE.NeutralToneMapping are built-inimplementations of tone mapping. 
+			THREE.CustomToneMapping expects a custom implementation by modyfing GLSL code of the material's fragment shader.
 			See the [example:webgl_tonemapping WebGL / tonemapping] example.
 		</p>
+		<p>
+			THREE.NeutralToneMapping is an implementation based on the Khronos 3D Commerce Group standard tone mapping.
+		</p>
 
 		<h2>Source</h2>
 		<p>

+ 6 - 8
docs/api/en/core/BufferGeometry.html

@@ -231,18 +231,16 @@
 
 		<h3>[method:undefined computeBoundingBox]()</h3>
 		<p>
-			Computes bounding box of the geometry, updating [page:.boundingBox]
-			attribute.<br />
-			Bounding boxes aren't computed by default. They need to be explicitly
-			computed, otherwise they are `null`.
+			Computes the bounding box of the geometry, and updates the [page:.boundingBox] attribute.
+			The bounding box is not computed by the engine; it must be computed by your app.
+			You may need to recompute the bounding box if the geometry vertices are modified.
 		</p>
 
 		<h3>[method:undefined computeBoundingSphere]()</h3>
 		<p>
-			Computes bounding sphere of the geometry, updating [page:.boundingSphere]
-			attribute.<br />
-			Bounding spheres aren't computed by default. They need to be explicitly
-			computed, otherwise they are `null`.
+			Computes the bounding sphere of the geometry, and updates the [page:.boundingSphere] attribute.
+			The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling.
+			You may need to recompute the bounding sphere if the geometry vertices are modified.
 		</p>
 
 		<h3>[method:undefined computeTangents]()</h3>

+ 22 - 0
docs/api/en/core/Object3D.html

@@ -604,6 +604,28 @@
 			Converts the vector from world space to this object's local space.
 		</p>
 
+		<h2>Events</h2>
+
+		<h3>added</h3>
+		<p>
+			Fires when the object has been added to its parent object.
+		</p>
+
+		<h3>removed</h3>
+		<p>
+			Fires when the object has been removed from its parent object.
+		</p>
+
+		<h3>childadded</h3>
+		<p>
+			Fires when a new child object has been added.
+		</p>
+
+		<h3>childremoved</h3>
+		<p>
+			Fires when a new child object has been removed.
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 10 - 4
docs/api/en/core/Raycaster.html

@@ -113,8 +113,8 @@
 			objects on layer `1` will be honored by the instance of [name].
 
 			<code>
-raycaster.layers.set( 1 ); 
-object.layers.enable( 1 ); 
+raycaster.layers.set( 1 );
+object.layers.enable( 1 );
 			</code>
 		</p>
 
@@ -123,12 +123,12 @@ object.layers.enable( 1 );
 			An object with the following properties:
 
 			<code>
-{ 
+{
 	Mesh: {},
 	Line: { threshold: 1 },
 	LOD: {},
 	Points: { threshold: 1 },
-	Sprite: {} 
+	Sprite: {}
 }
 			</code>
 
@@ -160,6 +160,12 @@ object.layers.enable( 1 );
 		</p>
 		<p>Updates the ray with a new origin and direction.</p>
 
+		<h3>[method:this setFromXRController]( [param:WebXRController controller] )</h3>
+		<p>
+			[page:WebXRController controller] — The controller to copy the position and direction from.
+		</p>
+		<p>Updates the ray with a new origin and direction.</p>
+
 		<h3>[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 			[page:Object3D object] — The object to check for intersection with the

+ 0 - 1
docs/api/en/core/bufferAttributeTypes/BufferAttributeTypes.html

@@ -18,7 +18,6 @@
 		</p>
 
 		<code>
-		THREE.Float64BufferAttribute 
 		THREE.Float32BufferAttribute
 		THREE.Float16BufferAttribute 
 		THREE.Uint32BufferAttribute

+ 1 - 1
docs/api/en/helpers/GridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 1 - 1
docs/api/en/helpers/PolarGridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 5 - 0
docs/api/en/materials/MeshBasicMaterial.html

@@ -99,6 +99,11 @@
 		<h3>[property:Texture envMap]</h3>
 		<p>The environment map. Default is null.</p>
 
+		<h3>[property:Euler envMapRotation]</h3>
+		<p>
+			The rotation of the environment map in radians. Default is `(0,0,0)`.
+		</p>
+
 		<h3>[property:Boolean fog]</h3>
 		<p>Whether the material is affected by fog. Default is `true`.</p>
 

+ 5 - 0
docs/api/en/materials/MeshLambertMaterial.html

@@ -165,6 +165,11 @@
 		<h3>[property:Texture envMap]</h3>
 		<p>The environment map. Default is null.</p>
 
+		<h3>[property:Euler envMapRotation]</h3>
+		<p>
+			The rotation of the environment map in radians. Default is `(0,0,0)`.
+		</p>
+
 		<h3>[property:Boolean flatShading]</h3>
 		<p>
 			Define whether the material is rendered with flat shading. Default is

+ 5 - 0
docs/api/en/materials/MeshPhongMaterial.html

@@ -163,6 +163,11 @@
 		<h3>[property:Texture envMap]</h3>
 		<p>The environment map. Default is null.</p>
 
+		<h3>[property:Euler envMapRotation]</h3>
+		<p>
+			The rotation of the environment map in radians. Default is `(0,0,0)`.
+		</p>
+
 		<h3>[property:Boolean flatShading]</h3>
 		<p>
 			Define whether the material is rendered with flat shading. Default is

+ 30 - 0
docs/api/en/materials/MeshPhysicalMaterial.html

@@ -17,12 +17,21 @@
 		</p>
 
 		<ul>
+			<li>
+				<b>Anisotropy:</b> Ability to represent the anisotropic property of materials 
+				as observable with brushed metals.
+			</li>
 			<li>
 				<b>Clearcoat:</b> Some materials — like car paints, carbon fiber, and
 				wet surfaces — require a clear, reflective layer on top of another layer
 				that may be irregular or rough. Clearcoat approximates this effect,
 				without the need for a separate transparent surface.
 			</li>
+			<li>
+				<b>Iridescence:</b> Allows to render the effect where hue varies 
+				depending on the viewing angle and illumination angle. This can be seen on
+				soap bubbles, oil films, or on the wings of many insects.
+			</li>
 			<li>
 				<b>Physically-based transparency:</b> One limitation of
 				[page:Material.opacity .opacity] is that highly transparent materials
@@ -69,7 +78,9 @@
 
 		<h2>Examples</h2>
 		<p>
+			[example:webgl_loader_gltf_anisotropy loader / gltf / anisotropy]<br />
 			[example:webgl_materials_physical_clearcoat materials / physical / clearcoat]<br />
+			[example:webgl_loader_gltf_iridescence loader / gltf / iridescence]<br />
 			[example:webgl_loader_gltf_sheen loader / gltf / sheen]<br />
 			[example:webgl_materials_physical_transmission materials / physical / transmission]
 		</p>
@@ -94,6 +105,25 @@
 			common properties.
 		</p>
 
+		<h3>[property:Float anisotropy]</h3>
+		<p>
+			The anisotropy strength. Default is `0.0`.
+		</p>
+
+		<h3>[property:Texture anisotropyMap]</h3>
+		<p>
+			Red and green channels represent the anisotropy direction in `[-1, 1]` tangent,
+			bitangent space, to be rotated by [page:.anisotropyRotation]. The blue channel
+			contains strength as `[0, 1]` to be multiplied by [page:.anisotropy]. Default is `null`.
+		</p>
+
+		<h3>[property:Float anisotropyRotation]</h3>
+		<p>
+			The rotation of the anisotropy in tangent, bitangent space, measured in radians
+			counter-clockwise from the tangent. When [page:.anisotropyMap] is present, this
+			property provides additional rotation to the vectors in the texture. Default is `0.0`.
+		</p>
+
 		<h3>[property:Color attenuationColor]</h3>
 		<p>
 			The color that white light turns into due to absorption when reaching the

+ 5 - 0
docs/api/en/materials/MeshStandardMaterial.html

@@ -193,6 +193,11 @@
 			[page:PMREMGenerator]. Default is null.
 		</p>
 
+		<h3>[property:Euler envMapRotation]</h3>
+		<p>
+			The rotation of the environment map in radians. Default is `(0,0,0)`.
+		</p>
+
 		<h3>[property:Float envMapIntensity]</h3>
 		<p>Scales the effect of the environment map by multiplying its color.</p>
 

+ 42 - 7
docs/api/en/objects/InstancedMesh.html

@@ -79,6 +79,13 @@
 			instanced data via [page:.setMatrixAt]().
 		</p>
 
+		<h3>[property:DataTexture morphTexture]</h3>
+		<p>
+			Represents the morph target weights of all instances. You have to set its
+			[page:Texture.needsUpdate needsUpdate] flag to true if you modify
+			instanced data via [page:.setMorphAt]().
+		</p>
+
 		<h3>[property:Boolean isInstancedMesh]</h3>
 		<p>Read-only flag to check if a given object is of type [name].</p>
 
@@ -87,17 +94,16 @@
 
 		<h3>[method:undefined computeBoundingBox]()</h3>
 		<p>
-			Computes the bounding box, updating [page:.boundingBox] attribute.<br />
-			Bounding boxes aren't computed by default. They need to be explicitly
-			computed, otherwise they are `null`.
+			Computes the bounding box of the instanced mesh, and updates the [page:.boundingBox] attribute.
+			The bounding box is not computed by the engine; it must be computed by your app.
+			You may need to recompute the bounding box if an instance is transformed via [page:.setMatrixAt]().
 		</p>
 
 		<h3>[method:undefined computeBoundingSphere]()</h3>
 		<p>
-			Computes the bounding sphere, updating [page:.boundingSphere]
-			attribute.<br />
-			Bounding spheres aren't computed by default. They need to be explicitly
-			computed, otherwise they are `null`.
+			Computes the bounding sphere of the instanced mesh, and updates the [page:.boundingSphere] attribute.
+			The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling.
+			You may need to recompute the bounding sphere if an instance is transformed via [page:.setMatrixAt]().
 		</p>
 
 		<h3>[method:undefined dispose]()</h3>
@@ -132,6 +138,18 @@
 		</p>
 		<p>Get the local transformation matrix of the defined instance.</p>
 
+		<h3>
+			[method:undefined getMorphAt]( [param:Integer index], [param:Mesh mesh] )
+		</h3>
+		<p>
+			[page:Integer index]: The index of an instance. Values have to be in the
+			range [0, count].
+		</p>
+		<p>
+			[page:Mesh mesh]: The [page:Mesh.morphTargetInfluences .morphTargetInfluences] property of this mesh will be filled with the morph target weights of the defined instance.
+		</p>
+		<p>Get the morph target weights of the defined instance.</p>
+
 		<h3>
 			[method:undefined setColorAt]( [param:Integer index], [param:Color color] )
 		</h3>
@@ -163,6 +181,23 @@
 			to true after updating all the matrices.
 		</p>
 
+		<h3>
+			[method:undefined setMorphAt]( [param:Integer index], [param:Mesh mesh] )
+		</h3>
+		<p>
+			[page:Integer index]: The index of an instance. Values have to be in the
+			range [0, count].
+		</p>
+		<p>
+			[page:Matrix4 matrix]: A mesh with [page:Mesh.morphTargetInfluences .morphTargetInfluences] property containing the morph target weights
+			of a single instance.
+		</p>
+		<p>
+			Sets the morph target weights to the defined instance. Make
+			sure you set [page:.morphTexture][page:Texture.needsUpdate .needsUpdate] 
+			to true after updating all the influences.
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 6 - 10
docs/api/en/objects/SkinnedMesh.html

@@ -151,20 +151,16 @@
 
 		<h3>[method:undefined computeBoundingBox]()</h3>
 		<p>
-			Computes the bounding box, updating [page:.boundingBox] attribute.<br />
-			Bounding boxes aren't computed by default. They need to be explicitly
-			computed, otherwise they are `null`. If an instance of [name] is animated,
-			this method should be called per frame to compute a correct bounding box.
+			Computes the bounding box of the skinned mesh, and updates the [page:.boundingBox] attribute.
+			The bounding box is not computed by the engine; it must be computed by your app.
+			If the skinned mesh is animated, the bounding box should be recomputed per frame.
 		</p>
 
 		<h3>[method:undefined computeBoundingSphere]()</h3>
 		<p>
-			Computes the bounding sphere, updating [page:.boundingSphere]
-			attribute.<br />
-			Bounding spheres aren't computed by default. They need to be explicitly
-			computed, otherwise they are `null`. If an instance of [name] is animated,
-			this method should be called per frame to compute a correct bounding
-			sphere.
+			Computes the bounding sphere of the skinned mesh, and updates the [page:.boundingSphere] attribute.
+			The bounding sphere is automatically computed by the engine when it is needed, e.g., for ray casting and view frustum culling.
+			If the skinned mesh is animated, the bounding sphere should be recomputed per frame.
 		</p>
 
 		<h3>[method:undefined normalizeSkinWeights]()</h3>

+ 0 - 75
docs/api/en/renderers/WebGLMultipleRenderTargets.html

@@ -1,75 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<base href="../../../" />
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		[page:WebGLRenderTarget] &rarr;
-
-		<h1>[name]</h1>
-
-		<p class="desc">
-			A special render target that enables a fragment shader to write to several
-			textures. This approach is useful for advanced rendering techniques like
-			post-processing or deferred rendering. Heads up: [name] can only be used
-			with a WebGL 2 rendering context.
-		</p>
-
-		<h2>Examples</h2>
-
-		<p>
-			[example:webgl2_multiple_rendertargets webgl2 / multiple / rendertargets ]
-		</p>
-
-		<h2>Constructor</h2>
-
-		<h3>
-			[name]([param:Number width], [param:Number height], [param:Number count],
-			[param:Object options])
-		</h3>
-
-		<p>
-			[page:Number width] - The width of the render target. Default is `1`.<br />
-			[page:Number height] - The height of the render target. Default is `1`.<br />
-			[page:Number count] - The number of render targets. Default is `1`.<br />
-
-			options - (optional object that holds texture parameters for an
-			auto-generated target texture and depthBuffer/stencilBuffer booleans. For
-			an explanation of the texture parameters see [page:Texture Texture]. For a
-			list of valid options, see [page:WebGLRenderTarget WebGLRenderTarget]).<br /><br />
-		</p>
-
-		<h2>Properties</h2>
-
-		<h3>[property:Boolean isWebGLMultipleRenderTargets]</h3>
-		<p>Read-only flag to check if a given object is of type [name].</p>
-
-		<h3>[property:Array texture]</h3>
-		<p>
-			The texture property is overwritten in [name] and replaced with an array.
-			This array holds the [page:WebGLRenderTarget.texture texture] references
-			of the respective render targets.
-		</p>
-
-		<p>
-			[page:WebGLRenderTarget WebGLRenderTarget] properties are available on
-			this class.
-		</p>
-
-		<h2>Methods</h2>
-
-		<p>
-			[page:WebGLRenderTarget WebGLRenderTarget] methods are available on this
-			class.
-		</p>
-
-		<h2>Source</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-		</p>
-	</body>
-</html>

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

@@ -49,7 +49,8 @@
 			<br />
 			[page:Boolean depthBuffer] - default is `true`. <br />
 			[page:Boolean stencilBuffer] - default is `false`.<br />
-			[page:Number samples] - default is `0`.<br /><br />
+			[page:Number samples] - default is `0`.<br />
+			[page:Number count] - default is `1`.<br /><br />
 
 			Creates a new [name]
 		</p>
@@ -83,6 +84,12 @@
 			further processing.
 		</p>
 
+		<h3>[property:Texture textures]</h3>
+		<p>
+			An array holding the [page:WebGLRenderTarget.texture texture] references
+			of multiple render targets configured with the [page:Number count] option.
+		</p>
+
 		<h3>[property:Boolean depthBuffer]</h3>
 		<p>Renders to the depth buffer. Default is true.</p>
 

+ 12 - 0
docs/api/en/scenes/Scene.html

@@ -49,6 +49,12 @@
 			textures. Default is `1`.
 		</p>
 
+		<h3>[property:Euler backgroundRotation]</h3>
+		<p>
+			The rotation of the background in radians. Only influences environment maps
+			assigned to [page:Scene.background]. Default is `(0,0,0)`.
+		</p>
+
 		<h3>[property:Texture environment]</h3>
 		<p>
 			Sets the environment map for all physical materials in the scene. However,
@@ -56,6 +62,12 @@
 			[page:MeshStandardMaterial.envMap]. Default is `null`.
 		</p>
 
+		<h3>[property:Euler environmentRotation]</h3>
+		<p>
+			The rotation of the environment map in radians. Only influences physical materials 
+			in the scene when [page:.environment] is used. Default is `(0,0,0)`.
+		</p>
+
 		<h3>[property:Fog fog]</h3>
 
 		<p>

+ 5 - 2
docs/api/fr/constants/Renderer.html

@@ -47,6 +47,7 @@
 		THREE.CineonToneMapping
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
+		THREE.NeutralToneMapping
 		THREE.CustomToneMapping
 		</code>
 		<p>
@@ -55,11 +56,13 @@
 		milieu de plage dynamique faible d'un écran d'ordinateur standard ou d'un écran d'appareil mobile.
 		</p>
 		<p>
-		THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping et THREE.AgXToneMapping sont des implémentations intégrées à la cartographie des tons.
+		THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping, THREE.AgXToneMapping et THREE.NeutralToneMapping sont des implémentations intégrées à la cartographie des tons.
 		THREE.CustomToneMapping attend une implémentation personnalisée en modifiant le code GLSL du fragment shader du matériau.
 		Voir l'exemple [example:webgl_tonemapping WebGL / tonemapping].
 		</p>
-
+		<p>
+			THREE.NeutralToneMapping is an implementation based on the Khronos 3D Commerce Group standard tone mapping.
+		</p>
 
 		<h2>Source</h2>
 

+ 5 - 1
docs/api/it/constants/Renderer.html

@@ -49,6 +49,7 @@
 		THREE.CineonToneMapping
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
+		THREE.NeutralToneMapping
 		THREE.CustomToneMapping
 		</code>
 		<p>
@@ -57,11 +58,14 @@
       gamma dinamica bassa del monitor di un computer o dello schermo di un dispositivo mobile.
 		</p>
 		<p>
-      THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping e THREE.AgXToneMapping sono implementazioni 
+      THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping THREE.AgXToneMapping e THREE.NeutralToneMapping sono implementazioni 
       integrate della mappatura dei toni.
       THREE.CustomToneMapping prevede un'implementazione personalizzata modificando il codice GLSL dello shader di frammenti del materiale.
       Vedi l'esempio [example:webgl_tonemapping WebGL / tonemapping].
 		</p>
+		<p>
+			THREE.NeutralToneMapping is an implementation based on the Khronos 3D Commerce Group standard tone mapping.
+		</p>
 
 
 		<h2>Source</h2>

+ 13 - 7
docs/api/it/core/Raycaster.html

@@ -97,7 +97,7 @@
 
 		<h3>[property:Camera camera]</h3>
 		<p>
-      La telecamera da utilizzare durante il raycast contro oggetti dipendenti dalla vista, come oggetti su cartelloni pubblicitari 
+      La telecamera da utilizzare durante il raycast contro oggetti dipendenti dalla vista, come oggetti su cartelloni pubblicitari
       come [page:Sprites]. Questo campo può essere settato manualmente o viene impostato quando si chiama il metodo "setFromCamera".
 
       L'impostazione predefinita è null.
@@ -156,12 +156,18 @@
 		  Aggiorna il raggio con una nuova origine e direzione.
 		</p>
 
+		<h3>[method:this setFromXRController]( [param:WebXRController controller] )</h3>
+		<p>
+			[page:WebXRController controller] — The controller to copy the position and direction from.
+		</p>
+		<p>Updates the ray with a new origin and direction.</p>
+
 		<h3>[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 		[page:Object3D object] — L'oggetto da verificare per l'intersezione con il raggio.<br />
-		[page:Boolean recursive] — Se true, controlla anche tutti i discendenti. Altrimenti controlla soltanto 
+		[page:Boolean recursive] — Se true, controlla anche tutti i discendenti. Altrimenti controlla soltanto
     l'intersezione con l'oggetto. Il valore predefinito è true.<br />
-		[page:Array optionalTarget] — (opzionale) obiettivo per impostare il risultato. 
+		[page:Array optionalTarget] — (opzionale) obiettivo per impostare il risultato.
     Altrimenti viene istanziato un nuovo [page:Array]. Se impostato, è necessario cancellare questo array prima di ogni chiamata (ad esempio, array.length = 0;).
 		</p>
 		<p>
@@ -183,8 +189,8 @@
 			[page:Integer instanceId] – Il numero di indice dell'istanza in cui il raggio interseca la InstancedMesh.
 		</p>
 		<p>
-      `Raycaster` delega al metodo [page:Object3D.raycast raycast] dell'oggetto passato, 
-      quando valuta se il raggio interseca l'oggetto o no. Ciò permette alle mesh di rispondere 
+      `Raycaster` delega al metodo [page:Object3D.raycast raycast] dell'oggetto passato,
+      quando valuta se il raggio interseca l'oggetto o no. Ciò permette alle mesh di rispondere
       in modo diverso al raycasting rispetto alle linee e alle nuvole di punti.
 		</p>
 		<p>
@@ -197,14 +203,14 @@
 		<h3>[method:Array intersectObjects]( [param:Array objects], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
       [page:Array objects] — Gli oggetti da controllare per l'intersezione con il raggio.<br />
-      [page:Boolean recursive] — Se true, controlla anche i discendenti degli oggetti. Altrimenti controlla soltanto 
+      [page:Boolean recursive] — Se true, controlla anche i discendenti degli oggetti. Altrimenti controlla soltanto
       l'intersezione con gli oggetti. Il valore predefinito è true.<br />
       [page:Array optionalTarget] — (opzionale) obiettivo per impostare il risultato.
       Altrimenti viene istanziato un nuovo [page:Array]. Se impostato, è necessario cancellare questo array prima di ogni chiamata (ad esempio, array.length = 0;).
 		</p>
 		<p>
       Controlla tutte le intersezioni tra il raggio e gli oggetti con o senza i discendenti.
-      Le intersezioni sono restituite ordinate per distanza, prima le più vicine. Le intersezioni 
+      Le intersezioni sono restituite ordinate per distanza, prima le più vicine. Le intersezioni
       hanno la stessa forma di quelle restituite da [page:.intersectObject].
 		</p>
 

+ 0 - 1
docs/api/it/core/bufferAttributeTypes/BufferAttributeTypes.html

@@ -17,7 +17,6 @@
 		</p>
 
 		<code>
-		THREE.Float64BufferAttribute
 		THREE.Float32BufferAttribute
 		THREE.Float16BufferAttribute
 		THREE.Uint32BufferAttribute

+ 1 - 1
docs/api/it/helpers/GridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 1 - 1
docs/api/it/helpers/PolarGridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 0 - 67
docs/api/it/renderers/WebGLMultipleRenderTargets.html

@@ -1,67 +0,0 @@
-<!DOCTYPE html>
-<html lang="it">
-	<head>
-		<meta charset="utf-8" />
-		<base href="../../../" />
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		[page:WebGLRenderTarget] &rarr;
-
-		<h1>[name]</h1>
-
-		<p class="desc">
-			Un target di rendering speciale che consente a un fragment shader di scrivere su più texture.
-			Questo approccio è utile per le tecniche di rendering avanzate come la post-eleborazione o il rendering differito.
-
-			Attenzione: [name] può solo essere utilizzato in un contesto di rendering WebGL 2.
-		</p>
-
-		<h2>Esempi</h2>
-
-		<p>
-			[example:webgl2_multiple_rendertargets webgl2 / multiple / rendertargets ]
-		</p>
-
-		<h2>Costruttore</h2>
-
-
-		<h3>[name]([param:Number width], [param:Number height], [param:Number count], [param:Object options])</h3>
-
-		<p>
-		[page:Number width] - La larghezza del target di rendering. Il valore predefinito è `1`.<br />
-		[page:Number height] - L'altezza del target di rendering. Il valore predefinito è `1`.<br />
-		[page:Number count] - Il numero di target di rendering. Il valore predefinito è `1`.<br />
-
-		options - (oggetto opzionale che contiene i parametri della texture per una texture target auto generata
-		e i booleani depthBuffer/stencilBuffer. Per una spiegazione dei parametri della texture consultare [page:Texture Texture].
-		Per un elenco di opzioni valide, consultare [page:WebGLRenderTarget WebGLRenderTarget].)<br /><br />
-		</p>
-
-		<h2>Proprietà</h2>
-
-		<h3>[property:Boolean isWebGLMultipleRenderTargets]</h3>
-		<p>
-			Flag di sola lettura per verificare se l'oggetto dato è di tipo [name].
-		</p>
-
-		<h3>[property:Array texture]</h3>
-		<p>
-			La proprietà texture viene sovrascritta in [name] e sostituita con un array. Questo array contiene i
-			riferimenti alla [page:WebGLRenderTarget.texture texture] dei rispettivi target di rendering.
-		</p>
-
-		<p>Le proprietà [page:WebGLRenderTarget WebGLRenderTarget] sono disponibili su questa classe.</p>
-
-		<h2>Metodi</h2>
-
-		<p>I metodi [page:WebGLRenderTarget WebGLRenderTarget] sono disponibili su questa classe.</p>
-
-		<h2>Source</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-		</p>
-	</body>
-</html>

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

@@ -42,7 +42,8 @@
 		[page:Constant colorSpace] - il valore predefinito è [page:Textures NoColorSpace]. <br />
 		[page:Boolean depthBuffer] - il valore predefinito è `true`. <br />
 		[page:Boolean stencilBuffer] - il valore predefinito è `false`.<br />
-		[page:Number samples] - il valore predefinito è 0.<br /><br />
+		[page:Number samples] - il valore predefinito è 0.<br />
+		[page:Number count] - default is `1`.<br /><br />
 
 		Crea un nuovo [name]
 		</p>
@@ -84,6 +85,12 @@
 			Questa istanza della texture contiene i pixel renderizzati. Utilizzalo come input per ulteriori informazioni.
 		</p>
 
+		<h3>[property:Texture textures]</h3>
+		<p>
+			An array holding the [page:WebGLRenderTarget.texture texture] references
+			of multiple render targets configured with the [page:Number count] option.
+		</p>
+
 		<h3>[property:Boolean depthBuffer]</h3>
 		<p>
 			Effettua il rendering al buffer di profondità. L'impostazione predefinita è `true`.

+ 4 - 1
docs/api/ko/constants/Renderer.html

@@ -47,6 +47,7 @@
 		THREE.CineonToneMapping
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
+		THREE.NeutralToneMapping
 		THREE.CustomToneMapping
 		</code>
 		<p>
@@ -56,7 +57,9 @@
 		[example:webgl_tonemapping WebGL / tonemapping] 예제를 참고하세요.
 
 		</p>
-
+		<p>
+			THREE.NeutralToneMapping is an implementation based on the Khronos 3D Commerce Group standard tone mapping.
+		</p>
 
 		<h2>소스 코드</h2>
 

+ 6 - 0
docs/api/ko/core/Raycaster.html

@@ -155,6 +155,12 @@
 		레이의 새 시점과 방향을 업데이트합니다.
 		</p>
 
+		<h3>[method:this setFromXRController]( [param:WebXRController controller] )</h3>
+		<p>
+			[page:WebXRController controller] — The controller to copy the position and direction from.
+		</p>
+		<p>Updates the ray with a new origin and direction.</p>
+
 		<h3>[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 		[page:Object3D object] — 레이와의 교차 체크를 하는 객체입니다.<br />

+ 0 - 1
docs/api/ko/core/bufferAttributeTypes/BufferAttributeTypes.html

@@ -17,7 +17,6 @@
 		</p>
 
 		<code>
-		THREE.Float64BufferAttribute
 		THREE.Float32BufferAttribute
 		THREE.Float16BufferAttribute
 		THREE.Uint32BufferAttribute

+ 5 - 1
docs/api/pt-br/constants/Renderer.html

@@ -47,6 +47,7 @@
 		THREE.CineonToneMapping
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
+		THREE.NeutralToneMapping
 		THREE.CustomToneMapping
 		</code>
 		<p>
@@ -55,10 +56,13 @@
 		médio da faixa dinâmica baixa de um monitor de computador padrão ou tela de dispositivo móvel.
 		</p>
 		<p>
-		THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping e THREE.AgXToneMapping são implementações internas de mapeamento de tom.
+		THREE.LinearToneMapping, THREE.ReinhardToneMapping, THREE.CineonToneMapping, THREE.ACESFilmicToneMapping, THREE.AgXToneMapping e THREE.NeutralToneMapping são implementações internas de mapeamento de tom.
 		THREE.CustomToneMapping espera uma implementação personalizada modificando o código GLSL do sombreador de fragmento do material.  
 		Vejo o exemplo [example:webgl_tonemapping WebGL / tonemapping].
 		</p>
+		<p>
+			THREE.NeutralToneMapping is an implementation based on the Khronos 3D Commerce Group standard tone mapping.
+		</p>
 
 		<h2>Source</h2>
 

+ 4 - 0
docs/api/zh/constants/CustomBlendingEquations.html

@@ -48,6 +48,10 @@
 		THREE.DstColorFactor
 		THREE.OneMinusDstColorFactor
 		THREE.SrcAlphaSaturateFactor
+		THREE.ConstantColorFactor
+		THREE.OneMinusConstantColorFactor
+		THREE.ConstantAlphaFactor
+		THREE.OneMinusConstantAlphaFactor
 		</code>
 
 		<h2>目标因子</h2>

+ 4 - 1
docs/api/zh/constants/Renderer.html

@@ -47,6 +47,7 @@
 		THREE.CineonToneMapping
 		THREE.ACESFilmicToneMapping
 		THREE.AgXToneMapping
+		THREE.NeutralToneMapping
 		THREE.CustomToneMapping
 		</code>
 		<p>
@@ -57,7 +58,9 @@
 		请查看示例:[example:webgl_tonemapping WebGL / tonemapping]。
 
 		</p>
-
+		<p>
+			THREE.NeutralToneMapping is an implementation based on the Khronos 3D Commerce Group standard tone mapping.
+		</p>
 
 		<h2>源代码</h2>
 

+ 6 - 0
docs/api/zh/core/Raycaster.html

@@ -159,6 +159,12 @@
 			使用一个新的原点和方向来更新射线。
 		</p>
 
+		<h3>[method:this setFromXRController]( [param:WebXRController controller] )</h3>
+		<p>
+			[page:WebXRController controller] — The controller to copy the position and direction from.
+		</p>
+		<p>Updates the ray with a new origin and direction.</p>
+
 		<h3>[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 		[page:Object3D object] —— 检查与射线相交的物体。<br />

+ 0 - 1
docs/api/zh/core/bufferAttributeTypes/BufferAttributeTypes.html

@@ -17,7 +17,6 @@
 		</p>
 
 		<code>
-		THREE.Float64BufferAttribute
 		THREE.Float32BufferAttribute
 		THREE.Float16BufferAttribute
 		THREE.Uint32BufferAttribute

+ 1 - 1
docs/api/zh/helpers/GridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 1 - 1
docs/api/zh/helpers/PolarGridHelper.html

@@ -7,7 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Object3D] &rarr; [page:Line] &rarr;
+		[page:Object3D] &rarr; [page:Line] &rarr; [page:LineSegments] &rarr;
 
 		<h1>[name]</h1>
 

+ 12 - 5
docs/api/zh/materials/Material.html

@@ -34,11 +34,18 @@
 </p>
 
 <h3>[property:Boolean alphaToCoverage]</h3>
-<p>
-	Enables alpha to coverage. Can only be used with MSAA-enabled contexts
-	(meaning when the renderer was created with *antialias* parameter set to
-	`true`). Enabling this will smooth aliasing on clip plane edges and alphaTest-clipped edges.
-	Default is `false`.
+<p>启用 alpha 覆盖。 只能与启用 MSAA 的上下文一起使用(意味着在创建渲染器时将抗锯齿参数 *antialias* 设置为 `true`)。
+	启用此选项将平滑剪裁平面边缘和 alphaTest 剪辑边缘上的锯齿。 默认值为 `false`。
+</p>
+
+<h3>[property:Float blendAlpha]</h3>
+<p>表示恒定混合颜色的 alpha 值。 默认值为 `0`。<br />
+	此属性仅在使用 [page:CustomBlendingEquation ConstantAlpha] 或 [page:CustomBlendingEquation OneMinusConstantAlpha] 自定义混合时有效。
+</p>
+
+<h3>[property:Color blendColor]</h3>
+<p>表示恒定混合颜色的 RGB 值。 默认值为 `0x000000`。<br />
+	此属性仅在使用 [page:CustomBlendingEquation ConstantColor] 或 [page:CustomBlendingEquation OneMinusConstantColor] 自定义混合时有效。
 </p>
 
 <h3>[property:Integer blendDst]</h3>

+ 0 - 61
docs/api/zh/renderers/WebGLMultipleRenderTargets.html

@@ -1,61 +0,0 @@
-<!DOCTYPE html>
-<html lang="zh">
-	<head>
-		<meta charset="utf-8" />
-		<base href="../../../" />
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		[page:WebGLRenderTarget] &rarr;
-
-		<h1>[name]</h1>
-
-		<p class="desc">
-			一个特殊的渲染目标,使片段着色器能够写入多个纹理。这种方法对于高级渲染技术很有用,例如后处理或延迟渲染。
-			
-			注意:[name]只能与 WebGL 2 渲染上下文一起使用。
-		</p>
-
-		<h2>例子(Examples)</h2>
-
-		<p>
-			[example:webgl2_multiple_rendertargets webgl2 / multiple / rendertargets ]
-		</p>
-
-		<h2>构造器(Constructor)</h2>
-
-
-		<h3>[name]([param:Number width], [param:Number height], [param:Number count])</h3>
-
-		<p>
-		[page:Number width] - 渲染目标的宽度。默认为`1`。<br />
-		[page:Number height] - 渲染目标的高度。默认为`1`。<br />
-		[page:Number count] - 渲染目标的数量。默认为`1`。
-		</p>
-
-		<h2>特性(Properties)</h2>
-
-		<h3>[property:Boolean isWebGLMultipleRenderTargets]</h3>
-		<p>
-			只读标志,用于检查给定对象是否属于[name]类型。
-		</p>
-
-		<h3>[property:Array texture]</h3>
-		<p>
-			纹理属性在[name]中被覆盖并替换为数组。该数组包含各个渲染目标的[page:WebGLRenderTarget.texture 纹理]引用。
-		</p>
-
-		<p>[page:WebGLRenderTarget WebGLRenderTarget]属性在此类上可用。</p>
-
-		<h2>方法(Methods)</h2>
-
-		<p>[page:WebGLRenderTarget WebGLRenderTarget]方法在此类上可用。</p>
-
-		<h2>源代码(Source)</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-		</p>
-	</body>
-</html>

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

@@ -38,7 +38,8 @@
 		[page:Constant colorSpace] - 默认是[page:Textures NoColorSpace]. <br />
 		[page:Boolean depthBuffer] - 默认是`true`.<br />
 		[page:Boolean stencilBuffer] - 默认是`false`.<br />
-		[page:Number samples] - 默认是`0`.<br /><br />
+		[page:Number samples] - 默认是`0`.<br />
+		[page:Number count] - default is `1`.<br /><br />
 
 		创建一个新[name]
 		</p>
@@ -80,6 +81,12 @@
 		纹理实例保存这渲染的像素,用作进一步处理的输入值
 		</p>
 
+		<h3>[property:Texture textures]</h3>
+		<p>
+			An array holding the [page:WebGLRenderTarget.texture texture] references
+			of multiple render targets configured with the [page:Number count] option.
+		</p>
+
 		<h3>[property:Boolean depthBuffer]</h3>
 		<p>
 		渲染到深度缓冲区。默认true.

+ 15 - 0
docs/examples/en/controls/DragControls.html

@@ -111,6 +111,16 @@
 			If set to `true`, [name] does not transform individual objects but the entire group. Default is `false`.
 		</p>
 
+		<h3>[property:String mode]</h3>
+		<p>
+			The current transformation mode. Possible values are `translate`, and `rotate`. Default is `translate`.
+		</p>
+
+		<h3>[property:Float rotateSpeed]</h3>
+		<p>
+			The speed at which the object will rotate when dragged in `rotate` mode. The higher the number the faster the rotation. Default is `1`.
+		</p>
+
 		<h2>Methods</h2>
 
 		<p>See the base [page:EventDispatcher] class for common methods.</p>
@@ -140,6 +150,11 @@
 			Returns the internal [page:Raycaster] instance that is used for intersection tests.
 		</p>
 
+		<h3>[method:undefined setObjects] ( [param:Array objects] )</h3>
+		<p>
+			Sets an array of draggable objects by overwriting the existing one.
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 6 - 6
docs/examples/en/loaders/3DMLoader.html

@@ -14,7 +14,7 @@
 			A loader for Rhinoceros 3d files and objects. <br /><br />
 			Rhinoceros is a 3D modeler used to create, edit, analyze, document, render, animate, and translate NURBS curves, surfaces, breps, extrusions, point clouds, as well as polygon meshes and SubD objects.
 			[link:https://github.com/mcneel/rhino3dm rhino3dm.js] is compiled to WebAssembly from the open source geometry library [link:https://github.com/mcneel/opennurbs openNURBS].
-			The loader currently uses [link:https://www.npmjs.com/package/rhino3dm/v/8.0.1 rhino3dm.js 8.0.1.]
+			The loader currently uses [link:https://www.npmjs.com/package/rhino3dm/v/8.4.0 rhino3dm.js 8.4.0.]
 		</p>
 
 		<h2>Import</h2>
@@ -166,7 +166,7 @@
 			// Specify path to a folder containing WASM/JS libraries or a CDN.
 			// For example, /jsm/libs/rhino3dm/ is the location of the library inside the three.js repository
 			// loader.setLibraryPath( '/path_to_library/rhino3dm/' );
-			loader.setLibraryPath( 'https://unpkg.com/rhino3dm@8.0.1/' );
+			loader.setLibraryPath( 'https://unpkg.com/rhino3dm@8.4.0/' );
 	
 			// Load a 3DM file
 			loader.load(
@@ -201,17 +201,17 @@
 		</p>
 		<p>
 		Parse a File3dm ArrayBuffer and call the `onLoad` function with the resulting Object3d.
-		See [link:https://github.com/mcneel/rhino-developer-samples/tree/7/rhino3dm/js/SampleParse3dmObjects this example] for further reference.
+		See [link:https://github.com/mcneel/rhino-developer-samples/tree/8/rhino3dm/js/SampleParse3dmObjects this example] for further reference.
 		</p>
 
 		<code>
-		import rhino3dm from 'https://unpkg.com/rhino3dm@8.0.1'
+		import rhino3dm from 'https://unpkg.com/rhino3dm@8.4.0'
 
 		// Instantiate a loader
 		const loader = new Rhino3dmLoader();
 
 		// Specify path to a folder containing WASM/JS libraries or a CDN.
-		loader.setLibraryPath( 'https://unpkg.com/rhino3dm@8.0.1' );
+		loader.setLibraryPath( 'https://unpkg.com/rhino3dm@8.4.0' );
 
 		const rhino = await rhino3dm();
 		console.log('Loaded rhino3dm.');
@@ -244,7 +244,7 @@
 		// Specify path to a folder containing the WASM/JS library:
 		loader.setLibraryPath( '/path_to_library/rhino3dm/' );
 		// or from a CDN:
-		loader.setLibraryPath( 'https://unpkg.com/rhino3dm@8.0.1' );
+		loader.setLibraryPath( 'https://unpkg.com/rhino3dm@8.4.0' );
 		</code>
 
 		<h3>[method:this setWorkerLimit]( [param:Number workerLimit] )</h3>

+ 3 - 3
docs/examples/en/loaders/GLTFLoader.html

@@ -53,7 +53,7 @@
 			<li>KHR_materials_unlit</li>
 			<li>KHR_materials_volume</li>
 			<li>KHR_mesh_quantization</li>
-			<li>KHR_lights_punctual<sup>1</sup></li>
+			<li>KHR_lights_punctual</li>
 			<li>KHR_texture_basisu</li>
 			<li>KHR_texture_transform</li>
 			<li>EXT_texture_webp</li>
@@ -66,12 +66,12 @@
 		</p>
 
 		<ul>
-			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]<sup>2</sup></li>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]<sup>1</sup></li>
 			<li>[link:https://github.com/takahirox/three-gltf-extensions MSFT_texture_dds]</li>
 		</ul>
 
 		<p><i>
-			<sup>2</sup>You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example].
+			<sup>1</sup>You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example].
 		</i></p>
 
 		<h2>Code Example</h2>

+ 10 - 0
docs/examples/ko/controls/DragControls.html

@@ -109,6 +109,11 @@
 			*true* 값으로 설정 되어있다면, [name]은 개별 객체가 아닌 전체 그룹은 드래그 합니다. 기본 값은 *false* 입니다.
 		</p>
 
+		<h3>[property:String mode]</h3>
+		<p>
+			The current transformation mode. Possible values are `translate`, and `rotate`. Default is `translate`.
+		</p>
+
 		<h2>메소드</h2>
 
 		<p>일반적인 메소드는 [page:EventDispatcher] 클래스를 참조하세요.</p>
@@ -138,6 +143,11 @@
 			Returns the internal [page:Raycaster] instance that is used for intersection tests.
 		</p>
 
+		<h3>[method:undefined setObjects] ( [param:Array objects] )</h3>
+		<p>
+			Sets an array of draggable objects by overwriting the existing one.
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 2 - 3
docs/examples/zh/animations/CCDIKSolver.html

@@ -180,9 +180,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/CCDIKSolver.js
-		examples/jsm/animation/CCDIKSolver.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/CCDIKSolver.js examples/jsm/animation/CCDIKSolver.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/animations/MMDAnimationHelper.html

@@ -178,9 +178,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/MMDAnimationHelper.js
-		examples/jsm/animation/MMDAnimationHelper.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/MMDAnimationHelper.js examples/jsm/animation/MMDAnimationHelper.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/animations/MMDPhysics.html

@@ -122,9 +122,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/MMDPhysics.js
-		examples/jsm/animation/MMDPhysics.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/animation/MMDPhysics.js examples/jsm/animation/MMDPhysics.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/controls/ArcballControls.html

@@ -279,9 +279,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/ArcballControls.js
-		examples/jsm/controls/ArcballControls.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/ArcballControls.js examples/jsm/controls/ArcballControls.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 10 - 0
docs/examples/zh/controls/DragControls.html

@@ -107,6 +107,11 @@
 			当[page:DragControls.objects]数组包含一个单个可拖拽的组对象时该选项生效。如果设置为`true`,[name]会转换整个组对象,而不对单个对象做转换。默认值为`false`。
 		</p>
 
+		<h3>[property:String mode]</h3>
+		<p>
+			The current transformation mode. Possible values are `translate`, and `rotate`. Default is `translate`.
+		</p>
+
 		<h2>方法</h2>
 
 		<p>共有方法请参见其基类[page:EventDispatcher]。</p>
@@ -136,6 +141,11 @@
 			返回用于相交测试的内部[page:Raycaster]实例。
 		</p>
 
+		<h3>[method:undefined setObjects] ( [param:Array objects] )</h3>
+		<p>
+			Sets an array of draggable objects by overwriting the existing one.
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 2 - 3
docs/examples/zh/controls/MapControls.html

@@ -111,9 +111,8 @@ controls.touches = {
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/MapControls.js
-		examples/jsm/controls/MapControls.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/MapControls.js examples/jsm/controls/MapControls.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/exporters/DRACOExporter.html

@@ -78,9 +78,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/DRACOExporter.js
-		examples/jsm/exporters/DRACOExporter.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/DRACOExporter.js examples/jsm/exporters/DRACOExporter.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/exporters/EXRExporter.html

@@ -88,9 +88,8 @@ ZIPS_COMPRESSION
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/EXRExporter.js
-		examples/jsm/exporters/EXRExporter.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/EXRExporter.js examples/jsm/exporters/EXRExporter.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/exporters/GLTFExporter.html

@@ -149,9 +149,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/GLTFExporter.js
-		examples/jsm/exporters/GLTFExporter.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/GLTFExporter.js examples/jsm/exporters/GLTFExporter.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/exporters/OBJExporter.html

@@ -60,9 +60,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/OBJExporter.js
-		examples/jsm/exporters/OBJExporter.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/OBJExporter.js examples/jsm/exporters/OBJExporter.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/exporters/PLYExporter.html

@@ -68,9 +68,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/PLYExporter.js
-		examples/jsm/exporters/PLYExporter.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/PLYExporter.js examples/jsm/exporters/PLYExporter.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/exporters/STLExporter.html

@@ -68,9 +68,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/STLExporter.js
-		examples/jsm/exporters/STLExporter.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/exporters/STLExporter.js examples/jsm/exporters/STLExporter.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/geometries/SDFGeometryGenerator.html

@@ -65,9 +65,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/SDFGeometry.js
-		examples/jsm/geometries/SDFGeometryGenerator.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/SDFGeometry.js examples/jsm/geometries/SDFGeometryGenerator.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/helpers/VertexTangentsHelper.html

@@ -87,9 +87,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/helpers/VertexTangentsHelper.js
-		examples/jsm/helpers/VertexTangentsHelper.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/helpers/VertexTangentsHelper.js examples/jsm/helpers/VertexTangentsHelper.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/loaders/3DMLoader.html

@@ -271,9 +271,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/3DMLoader.js
-		examples/jsm/loaders/3DMLoader.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/3DMLoader.js examples/jsm/loaders/3DMLoader.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 4 - 14
docs/examples/zh/loaders/GLTFLoader.html

@@ -52,9 +52,9 @@
 			<li>KHR_materials_unlit</li>
 			<li>KHR_materials_volume</li>
 			<li>KHR_mesh_quantization</li>
-			<li>KHR_lights_punctual<sup>1</sup></li>
+			<li>KHR_lights_punctual</li>
 			<li>KHR_texture_basisu</li>
-			<li>KHR_texture_transform<sup>2</sup></li>
+			<li>KHR_texture_transform</li>
 			<li>EXT_texture_webp</li>
 			<li>EXT_meshopt_compression</li>
 			<li>EXT_mesh_gpu_instancing</li>
@@ -65,22 +65,12 @@
 		</p>
 
 		<ul>
-			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]<sup>3</sup></li>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]<sup>1</sup></li>
 			<li>[link:https://github.com/takahirox/three-gltf-extensions MSFT_texture_dds]</li>
 		</ul>
 
 		<p><i>
-			<sup>2</sup>支持UV变换,但存在一些重要的限制。
-			Transforms applied to
-			a texture using the first UV slot (all textures except aoMap and lightMap) must share the same
-			transform, or no transform at all.
-			aoMap 和 lightMap 纹理不能被变换。每个材质最多只能使用一次变换。
-			请参阅#[link:https://github.com/mrdoob/three.js/pull/13831 13831] 和
-			#[link:https://github.com/mrdoob/three.js/issues/12788 12788]。
-		</i></p>
-
-		<p><i>
-			<sup>3</sup>You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example].
+			<sup>1</sup>You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example].
 		</i></p>
 
 		<h2>代码示例</h2>

+ 2 - 3
docs/examples/zh/loaders/KTX2Loader.html

@@ -134,9 +134,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/KTX2Loader.js
-		examples/jsm/loaders/KTX2Loader.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/KTX2Loader.js examples/jsm/loaders/KTX2Loader.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/loaders/LDrawLoader.html

@@ -211,9 +211,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/LDrawLoader.js
-		examples/jsm/loaders/LDrawLoader.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/LDrawLoader.js examples/jsm/loaders/LDrawLoader.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/loaders/PDBLoader.html

@@ -109,9 +109,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PDBLoader.js
-		examples/jsm/loaders/PDBLoader.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/PDBLoader.js examples/jsm/loaders/PDBLoader.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/math/MeshSurfaceSampler.html

@@ -90,9 +90,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/MeshSurfaceSampler.js
-		examples/jsm/math/MeshSurfaceSampler.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/MeshSurfaceSampler.js examples/jsm/math/MeshSurfaceSampler.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/math/convexhull/ConvexHull.html

@@ -230,9 +230,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js
-		examples/jsm/math/ConvexHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/math/convexhull/Face.html

@@ -103,9 +103,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js
-		examples/jsm/math/ConvexHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/math/convexhull/HalfEdge.html

@@ -90,9 +90,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js
-		examples/jsm/math/ConvexHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/math/convexhull/VertexList.html

@@ -109,9 +109,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js
-		examples/jsm/math/ConvexHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js]
 	<p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/math/convexhull/VertexNode.html

@@ -61,9 +61,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js
-		examples/jsm/math/ConvexHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/math/ConvexHull.js examples/jsm/math/ConvexHull.js]
 	<p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/utils/CameraUtils.html

@@ -38,9 +38,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/utils/CameraUtils.js
-		examples/jsm/utils/CameraUtils.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/utils/CameraUtils.js examples/jsm/utils/CameraUtils.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 2 - 3
docs/examples/zh/webxr/XREstimatedLight.html

@@ -109,9 +109,8 @@
 	<h2>源代码</h2>
 
 	<p>
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/webxr/XREstimatedLight.js
-		examples/jsm/webxr/XREstimatedLight.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/webxr/XREstimatedLight.js examples/jsm/webxr/XREstimatedLight.js]
 	</p>
 </body>
 
-</html>
+</html>

+ 0 - 5
docs/list.json

@@ -278,7 +278,6 @@
 			},
 
 			"Renderers": {
-				"WebGLMultipleRenderTargets": "api/en/renderers/WebGLMultipleRenderTargets",
 				"WebGLRenderer": "api/en/renderers/WebGLRenderer",
 				"WebGL1Renderer": "api/en/renderers/WebGL1Renderer",
 				"WebGLRenderTarget": "api/en/renderers/WebGLRenderTarget",
@@ -720,7 +719,6 @@
 			},
 
 			"Renderers": {
-				"WebGLMultipleRenderTargets": "api/ar/renderers/WebGLMultipleRenderTargets",
 				"WebGLRenderer": "api/ar/renderers/WebGLRenderer",
 				"WebGL1Renderer": "api/ar/renderers/WebGL1Renderer",
 				"WebGLRenderTarget": "api/ar/renderers/WebGLRenderTarget",
@@ -1028,7 +1026,6 @@
 			},
 
 			"渲染器": {
-				"WebGLMultipleRenderTargets": "api/zh/renderers/WebGLMultipleRenderTargets",
 				"WebGLRenderer": "api/zh/renderers/WebGLRenderer",
 				"WebGL1Renderer": "api/zh/renderers/WebGL1Renderer",
 				"WebGLRenderTarget": "api/zh/renderers/WebGLRenderTarget",
@@ -1665,7 +1662,6 @@
 			},
 
 			"Renderers": {
-				"WebGLMultipleRenderTargets": "api/it/renderers/WebGLMultipleRenderTargets",
 				"WebGLRenderer": "api/it/renderers/WebGLRenderer",
 				"WebGL1Renderer": "api/it/renderers/WebGL1Renderer",
 				"WebGLRenderTarget": "api/it/renderers/WebGLRenderTarget",
@@ -2193,7 +2189,6 @@
 			},
 
 			"Renderers": {
-				"WebGLMultipleRenderTargets": "api/en/renderers/WebGLMultipleRenderTargets",
 				"WebGLRenderer": "api/en/renderers/WebGLRenderer",
 				"WebGL1Renderer": "api/en/renderers/WebGL1Renderer",
 				"WebGLRenderTarget": "api/en/renderers/WebGLRenderTarget",

+ 30 - 1
docs/manual/en/introduction/How-to-update-things.html

@@ -190,7 +190,6 @@ line.geometry.computeBoundingSphere();
 
 		</div>
 
-
 		<h2>Cameras</h2>
 		<div>
 			<p>A camera's position and target is updated automatically. If you need to change</p>
@@ -216,5 +215,35 @@ camera.aspect = window.innerWidth / window.innerHeight;
 camera.updateProjectionMatrix();
 			</code>
 		</div>
+
+		<h2>InstancedMesh</h2>
+		<div>
+			<p>
+				`InstancedMesh` is a class for conveniently access instanced rendering in `three.js`. Certain library features like view frustum culling or
+				ray casting rely on up-to-date bounding volumes (bounding sphere and bounding box). Because of the way how `InstancedMesh` works, the class 
+				has its own [page:InstancedMesh.boundingBox boundingBox] and [page:InstancedMesh.boundingSphere boundingSphere] properties that supersede
+				the bounding volumes on geometry level.
+			</p>
+			<p>
+				Similar to geometries you have to recompute the bounding box and sphere whenever you change the underlying data. In context of `InstancedMesh`, that
+				happens when you transform instances via [page:InstancedMesh.setMatrixAt setMatrixAt](). You can use the same pattern like with geometries.
+			</p>
+			<code>
+instancedMesh.computeBoundingBox();
+instancedMesh.computeBoundingSphere();
+			</code>
+
+		</div>
+
+		<h2>SkinnedMesh</h2>
+		<div>
+			<p>
+				`SkinnedMesh` follows the same principles like `InstancedMesh` in context of bounding volumes. Meaning the class has its own version of
+				[page:SkinnedMesh.boundingBox boundingBox] and [page:SkinnedMesh.boundingSphere boundingSphere] to correctly enclose animated meshes.
+				When calling `computeBoundingBox()` and `computeBoundingSphere()`, the class computes the respective bounding volumes based on the current
+				bone tranformation (or in other words the current animation state).
+			</p>
+		</div>
+
 	</body>
 </html>

+ 3 - 0
docs/manual/en/introduction/Matrix-transformations.html

@@ -54,6 +54,9 @@ object.matrixAutoUpdate = false;
 		<p>
 		When either the parent or the child object's transformation changes, you can request that the child object's [page:Object3D.matrixWorld matrixWorld] be updated by calling [page:Object3D.updateMatrixWorld updateMatrixWorld]().
 		</p>
+		<p>
+		An object can be transformed via [page:Object3D.applyMatrix4]. Note: Under-the-hood, this method relies on [page:Matrix4.decompose], and not all matrices are decomposable in this way. For example, if an object has a non-uniformly scaled parent, then the object's world matrix may not be decomposable, and this method may not be appropriate.
+		</p>
 
 		<h2>Rotation and Quaternion</h2>
 		<p>

+ 15 - 9
editor/css/main.css

@@ -67,7 +67,7 @@ textarea, input { outline: none; } /* osx */
 	position: relative;
 	display: block;
 	width: 100%;
-	min-width: 260px;
+	min-width: 335px;
 }
 
 .TabbedPanel .Tabs {
@@ -77,7 +77,7 @@ textarea, input { outline: none; } /* osx */
 }
 
 	.TabbedPanel .Tabs .Tab {
-		padding: 10px;
+		padding: 10px 9px;
 		text-transform: uppercase;
 	}
 
@@ -93,7 +93,7 @@ textarea, input { outline: none; } /* osx */
 	background-color: #fff;
 	padding: 0;
 	width: 100%;
-	min-height: 140px;
+	min-height: 180px;
 	font-size: 12px;
 	cursor: default;
 	overflow: auto;
@@ -293,7 +293,7 @@ select {
 #resizer {
 	position: absolute;
 	top: 32px;
-	right: 295px;
+	right: 345px;
 	width: 5px;
 	bottom: 0px;
 	/* background-color: rgba(255,0,0,0.5); */
@@ -304,7 +304,7 @@ select {
 	position: absolute;
 	top: 32px;
 	left: 0;
-	right: 300px;
+	right: 350px;
 	bottom: 0;
 }
 
@@ -317,7 +317,7 @@ select {
 	position: absolute;
 	top: 32px;
 	left: 0;
-	right: 300px;
+	right: 350px;
 	bottom: 0;
 	opacity: 0.9;
 }
@@ -326,7 +326,7 @@ select {
 	position: absolute;
 	top: 32px;
 	left: 0;
-	right: 300px;
+	right: 350px;
 	bottom: 0;
 }
 
@@ -409,7 +409,7 @@ select {
 	right: 0;
 	top: 32px;
 	bottom: 0;
-	width: 300px;
+	width: 350px;
 	background: #eee;
 	overflow: auto;
 }
@@ -431,6 +431,12 @@ select {
 		margin-bottom: 10px;
 	}
 
+	#sidebar .Row .Label {
+
+		width: 120px;
+
+	}
+
 #tabs {
 	background-color: #ddd;
 	border-top: 1px solid #ccc;
@@ -470,7 +476,7 @@ select {
 	background-color: #fff;
 	padding: 0;
 	width: 100%;
-	height: 140px;
+	height: 180px;
 	font-size: 12px;
 	cursor: default;
 	overflow: auto;

+ 2 - 4
editor/index.html

@@ -61,8 +61,8 @@
 					"three/addons/": "../examples/jsm/",
 
 					"three/examples/": "../examples/",
-					"three-gpu-pathtracer": "https://unpkg.com/[email protected]7/build/index.module.js",
-					"three-mesh-bvh": "https://unpkg.com/[email protected].0/build/index.module.js"
+					"three-gpu-pathtracer": "https://unpkg.com/[email protected]9/build/index.module.js",
+					"three-mesh-bvh": "https://unpkg.com/[email protected].3/build/index.module.js"
 				}
 			}
 		</script>
@@ -79,7 +79,6 @@
 			import { Sidebar } from './js/Sidebar.js';
 			import { Menubar } from './js/Menubar.js';
 			import { Resizer } from './js/Resizer.js';
-			import { VRButton } from 'three/addons/webxr/VRButton.js';
 
 			window.URL = window.URL || window.webkitURL;
 			window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
@@ -96,7 +95,6 @@
 
 			window.editor = editor; // Expose editor to Console
 			window.THREE = THREE; // Expose THREE to APP Scripts and Console
-			window.VRButton = VRButton; // Expose VRButton to APP Scripts
 
 			const viewport = new Viewport( editor );
 			document.body.appendChild( viewport.dom );

+ 43 - 6
editor/js/Editor.js

@@ -5,7 +5,7 @@ import { Loader } from './Loader.js';
 import { History as _History } from './History.js';
 import { Strings } from './Strings.js';
 import { Storage as _Storage } from './Storage.js';
-import { Selector } from './Viewport.Selector.js';
+import { Selector } from './Selector.js';
 
 var _DEFAULT_CAMERA = new THREE.PerspectiveCamera( 50, 1, 0.01, 1000 );
 _DEFAULT_CAMERA.name = 'Camera';
@@ -27,10 +27,11 @@ function Editor() {
 		startPlayer: new Signal(),
 		stopPlayer: new Signal(),
 
-		// vr
+		// xr
 
-		toggleVR: new Signal(),
-		exitedVR: new Signal(),
+		enterXR: new Signal(),
+		offerXR: new Signal(),
+		leaveXR: new Signal(),
 
 		// notifications
 
@@ -96,9 +97,9 @@ function Editor() {
 
 	this.config = new Config();
 	this.history = new _History( this );
+	this.selector = new Selector( this );
 	this.storage = new _Storage();
 	this.strings = new Strings( this.config );
-	this.selector = new Selector( this );
 
 	this.loader = new Loader( this );
 
@@ -108,6 +109,7 @@ function Editor() {
 	this.scene.name = 'Scene';
 
 	this.sceneHelpers = new THREE.Scene();
+	this.sceneHelpers.add( new THREE.HemisphereLight( 0xffffff, 0x888888, 2 ) );
 
 	this.object = {};
 	this.geometries = {};
@@ -711,7 +713,6 @@ Editor.prototype = {
 			project: {
 				shadows: this.config.getKey( 'project/renderer/shadows' ),
 				shadowType: this.config.getKey( 'project/renderer/shadowType' ),
-				vr: this.config.getKey( 'project/vr' ),
 				toneMapping: this.config.getKey( 'project/renderer/toneMapping' ),
 				toneMappingExposure: this.config.getKey( 'project/renderer/toneMappingExposure' )
 			},
@@ -747,8 +748,44 @@ Editor.prototype = {
 
 		this.history.redo();
 
+	},
+
+	utils: {
+
+		save: save,
+		saveArrayBuffer: saveArrayBuffer,
+		saveString: saveString
+
 	}
 
 };
 
+const link = document.createElement( 'a' );
+
+function save( blob, filename ) {
+
+	if ( link.href ) {
+
+		URL.revokeObjectURL( link.href );
+
+	}
+
+	link.href = URL.createObjectURL( blob );
+	link.download = filename || 'data.json';
+	link.dispatchEvent( new MouseEvent( 'click' ) );
+
+}
+
+function saveArrayBuffer( buffer, filename ) {
+
+	save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
+
+}
+
+function saveString( text, filename ) {
+
+	save( new Blob( [ text ], { type: 'text/plain' } ), filename );
+
+}
+
 export { Editor };

+ 125 - 44
editor/js/EditorControls.js

@@ -31,6 +31,9 @@ class EditorControls extends THREE.EventDispatcher {
 		var spherical = new THREE.Spherical();
 		var sphere = new THREE.Sphere();
 
+		var pointers = [];
+		var pointerPositions = {};
+
 		// events
 
 		var changeEvent = { type: 'change' };
@@ -122,19 +125,32 @@ class EditorControls extends THREE.EventDispatcher {
 
 			if ( scope.enabled === false ) return;
 
-			switch ( event.pointerType ) {
+			if ( pointers.length === 0 ) {
 
-				case 'mouse':
-				case 'pen':
-					onMouseDown( event );
-					break;
+				domElement.setPointerCapture( event.pointerId );
 
-				// TODO touch
+				domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
+				domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
 
 			}
 
-			domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
-			domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
+			//
+
+			if ( isTrackingPointer( event ) ) return;
+
+			//
+
+			addPointer( event );
+
+			if ( event.pointerType === 'touch' ) {
+
+				onTouchStart( event );
+
+			} else {
+
+				onMouseDown( event );
+
+			}
 
 		}
 
@@ -142,14 +158,13 @@ class EditorControls extends THREE.EventDispatcher {
 
 			if ( scope.enabled === false ) return;
 
-			switch ( event.pointerType ) {
+			if ( event.pointerType === 'touch' ) {
 
-				case 'mouse':
-				case 'pen':
-					onMouseMove( event );
-					break;
+				onTouchMove( event );
 
-				// TODO touch
+			} else {
+
+				onMouseMove( event );
 
 			}
 
@@ -157,19 +172,30 @@ class EditorControls extends THREE.EventDispatcher {
 
 		function onPointerUp( event ) {
 
-			switch ( event.pointerType ) {
+			removePointer( event );
+
+			switch ( pointers.length ) {
+
+				case 0:
+
+					domElement.releasePointerCapture( event.pointerId );
+
+					domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
+					domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
 
-				case 'mouse':
-				case 'pen':
-					onMouseUp();
 					break;
 
-				// TODO touch
+				case 1:
 
-			}
+					var pointerId = pointers[ 0 ];
+					var position = pointerPositions[ pointerId ];
 
-			domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-			domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+					// minimal placeholder event - allows state correction on pointer-up
+					onTouchStart( { pointerId: pointerId, pageX: position.x, pageY: position.y } );
+
+					break;
+
+			}
 
 		}
 
@@ -251,9 +277,6 @@ class EditorControls extends THREE.EventDispatcher {
 
 			domElement.removeEventListener( 'pointerdown', onPointerDown );
 
-			domElement.removeEventListener( 'touchstart', touchStart );
-			domElement.removeEventListener( 'touchmove', touchMove );
-
 		};
 
 		domElement.addEventListener( 'contextmenu', contextmenu );
@@ -269,20 +292,23 @@ class EditorControls extends THREE.EventDispatcher {
 
 		var prevDistance = null;
 
-		function touchStart( event ) {
+		function onTouchStart( event ) {
 
-			if ( scope.enabled === false ) return;
+			trackPointer( event );
 
-			switch ( event.touches.length ) {
+			switch ( pointers.length ) {
 
 				case 1:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
 					break;
 
 				case 2:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+
+					var position = getSecondPointerPosition( event );
+
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( position.x, position.y, 0 ).divideScalar( window.devicePixelRatio );
 					prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] );
 					break;
 
@@ -294,12 +320,9 @@ class EditorControls extends THREE.EventDispatcher {
 		}
 
 
-		function touchMove( event ) {
-
-			if ( scope.enabled === false ) return;
+		function onTouchMove( event ) {
 
-			event.preventDefault();
-			event.stopPropagation();
+			trackPointer( event );
 
 			function getClosest( touch, touches ) {
 
@@ -315,17 +338,20 @@ class EditorControls extends THREE.EventDispatcher {
 
 			}
 
-			switch ( event.touches.length ) {
+			switch ( pointers.length ) {
 
 				case 1:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
 					scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ], prevTouches ) ).multiplyScalar( - 1 ) );
 					break;
 
 				case 2:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+
+					var position = getSecondPointerPosition( event );
+
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( position.x, position.y, 0 ).divideScalar( window.devicePixelRatio );
 					var distance = touches[ 0 ].distanceTo( touches[ 1 ] );
 					scope.zoom( delta.set( 0, 0, prevDistance - distance ) );
 					prevDistance = distance;
@@ -347,8 +373,63 @@ class EditorControls extends THREE.EventDispatcher {
 
 		}
 
-		domElement.addEventListener( 'touchstart', touchStart, { passive: false } );
-		domElement.addEventListener( 'touchmove', touchMove, { passive: false } );
+		function addPointer( event ) {
+
+			pointers.push( event.pointerId );
+
+		}
+
+		function removePointer( event ) {
+
+			delete pointerPositions[ event.pointerId ];
+
+			for ( var i = 0; i < pointers.length; i ++ ) {
+
+				if ( pointers[ i ] == event.pointerId ) {
+
+					pointers.splice( i, 1 );
+					return;
+
+				}
+
+			}
+
+		}
+
+		function isTrackingPointer( event ) {
+
+			for ( var i = 0; i < pointers.length; i ++ ) {
+
+				if ( pointers[ i ] == event.pointerId ) return true;
+
+			}
+
+			return false;
+
+		}
+
+		function trackPointer( event ) {
+
+			var position = pointerPositions[ event.pointerId ];
+
+			if ( position === undefined ) {
+
+				position = new THREE.Vector2();
+				pointerPositions[ event.pointerId ] = position;
+
+			}
+
+			position.set( event.pageX, event.pageY );
+
+		}
+
+		function getSecondPointerPosition( event ) {
+
+			var pointerId = ( event.pointerId === pointers[ 0 ] ) ? pointers[ 1 ] : pointers[ 0 ];
+
+			return pointerPositions[ pointerId ];
+
+		}
 
 	}
 

+ 1 - 18
editor/js/Menubar.Edit.js

@@ -47,23 +47,6 @@ function MenubarEdit( editor ) {
 	} );
 	options.add( redo );
 
-	// Clear History
-
-	let option = new UIRow();
-	option.setClass( 'option' );
-	option.setTextContent( strings.getKey( 'menubar/edit/clear_history' ) );
-	option.onClick( function () {
-
-		if ( confirm( 'The Undo/Redo History will be cleared. Are you sure?' ) ) {
-
-			editor.history.clear();
-
-		}
-
-	} );
-	options.add( option );
-
-
 	editor.signals.historyChanged.add( function () {
 
 		const history = editor.history;
@@ -91,7 +74,7 @@ function MenubarEdit( editor ) {
 
 	// Center
 
-	option = new UIRow();
+	let option = new UIRow();
 	option.setClass( 'option' );
 	option.setTextContent( strings.getKey( 'menubar/edit/center' ) );
 	option.onClick( function () {

+ 3 - 224
editor/js/Menubar.File.js

@@ -1,14 +1,12 @@
-import * as THREE from 'three';
-
-import { zipSync, strToU8 } from 'three/addons/libs/fflate.module.js';
-
 import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js';
 
 function MenubarFile( editor ) {
 
-	const config = editor.config;
 	const strings = editor.strings;
 
+	const saveArrayBuffer = editor.utils.saveArrayBuffer;
+	const saveString = editor.utils.saveString;
+
 	const container = new UIPanel();
 	container.setClass( 'menu' );
 
@@ -72,112 +70,6 @@ function MenubarFile( editor ) {
 
 	options.add( new UIHorizontalRule() );
 
-	// Export Geometry
-
-	option = new UIRow();
-	option.setClass( 'option' );
-	option.setTextContent( strings.getKey( 'menubar/file/export/geometry' ) );
-	option.onClick( function () {
-
-		const object = editor.selected;
-
-		if ( object === null ) {
-
-			alert( 'No object selected.' );
-			return;
-
-		}
-
-		const geometry = object.geometry;
-
-		if ( geometry === undefined ) {
-
-			alert( 'The selected object doesn\'t have geometry.' );
-			return;
-
-		}
-
-		let output = geometry.toJSON();
-
-		try {
-
-			output = JSON.stringify( output, null, '\t' );
-			output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
-
-		} catch ( e ) {
-
-			output = JSON.stringify( output );
-
-		}
-
-		saveString( output, 'geometry.json' );
-
-	} );
-	options.add( option );
-
-	// Export Object
-
-	option = new UIRow();
-	option.setClass( 'option' );
-	option.setTextContent( strings.getKey( 'menubar/file/export/object' ) );
-	option.onClick( function () {
-
-		const object = editor.selected;
-
-		if ( object === null ) {
-
-			alert( 'No object selected' );
-			return;
-
-		}
-
-		let output = object.toJSON();
-
-		try {
-
-			output = JSON.stringify( output, null, '\t' );
-			output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
-
-		} catch ( e ) {
-
-			output = JSON.stringify( output );
-
-		}
-
-		saveString( output, 'model.json' );
-
-	} );
-	options.add( option );
-
-	// Export Scene
-
-	option = new UIRow();
-	option.setClass( 'option' );
-	option.setTextContent( strings.getKey( 'menubar/file/export/scene' ) );
-	option.onClick( function () {
-
-		let output = editor.scene.toJSON();
-
-		try {
-
-			output = JSON.stringify( output, null, '\t' );
-			output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
-
-		} catch ( e ) {
-
-			output = JSON.stringify( output );
-
-		}
-
-		saveString( output, 'scene.json' );
-
-	} );
-	options.add( option );
-
-	//
-
-	options.add( new UIHorizontalRule() );
-
 	// Export DRC
 
 	option = new UIRow();
@@ -393,119 +285,6 @@ function MenubarFile( editor ) {
 
 	//
 
-	options.add( new UIHorizontalRule() );
-
-	// Publish
-
-	option = new UIRow();
-	option.setClass( 'option' );
-	option.setTextContent( strings.getKey( 'menubar/file/publish' ) );
-	option.onClick( function () {
-
-		const toZip = {};
-
-		//
-
-		let output = editor.toJSON();
-		output.metadata.type = 'App';
-		delete output.history;
-
-		output = JSON.stringify( output, null, '\t' );
-		output = output.replace( /[\n\t]+([\d\.e\-\[\]]+)/g, '$1' );
-
-		toZip[ 'app.json' ] = strToU8( output );
-
-		//
-
-		const title = config.getKey( 'project/title' );
-
-		const manager = new THREE.LoadingManager( function () {
-
-			const zipped = zipSync( toZip, { level: 9 } );
-
-			const blob = new Blob( [ zipped.buffer ], { type: 'application/zip' } );
-
-			save( blob, ( title !== '' ? title : 'untitled' ) + '.zip' );
-
-		} );
-
-		const loader = new THREE.FileLoader( manager );
-		loader.load( 'js/libs/app/index.html', function ( content ) {
-
-			content = content.replace( '<!-- title -->', title );
-
-			const includes = [];
-
-			content = content.replace( '<!-- includes -->', includes.join( '\n\t\t' ) );
-
-			let editButton = '';
-
-			if ( config.getKey( 'project/editable' ) ) {
-
-				editButton = [
-					'			let button = document.createElement( \'a\' );',
-					'			button.href = \'https://threejs.org/editor/#file=\' + location.href.split( \'/\' ).slice( 0, - 1 ).join( \'/\' ) + \'/app.json\';',
-					'			button.style.cssText = \'position: absolute; bottom: 20px; right: 20px; padding: 10px 16px; color: #fff; border: 1px solid #fff; border-radius: 20px; text-decoration: none;\';',
-					'			button.target = \'_blank\';',
-					'			button.textContent = \'EDIT\';',
-					'			document.body.appendChild( button );',
-				].join( '\n' );
-
-			}
-
-			content = content.replace( '\t\t\t/* edit button */', editButton );
-
-			toZip[ 'index.html' ] = strToU8( content );
-
-		} );
-		loader.load( 'js/libs/app.js', function ( content ) {
-
-			toZip[ 'js/app.js' ] = strToU8( content );
-
-		} );
-		loader.load( '../build/three.module.js', function ( content ) {
-
-			toZip[ 'js/three.module.js' ] = strToU8( content );
-
-		} );
-		loader.load( '../examples/jsm/webxr/VRButton.js', function ( content ) {
-
-			toZip[ 'js/VRButton.js' ] = strToU8( content );
-
-		} );
-
-	} );
-	options.add( option );
-
-	//
-
-	const link = document.createElement( 'a' );
-	function save( blob, filename ) {
-
-		if ( link.href ) {
-
-			URL.revokeObjectURL( link.href );
-
-		}
-
-		link.href = URL.createObjectURL( blob );
-		link.download = filename || 'data.json';
-		link.dispatchEvent( new MouseEvent( 'click' ) );
-
-	}
-
-	function saveArrayBuffer( buffer, filename ) {
-
-		save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
-
-	}
-
-	function saveString( text, filename ) {
-
-		save( new Blob( [ text ], { type: 'text/plain' } ), filename );
-
-	}
-
 	function getAnimations( scene ) {
 
 		const animations = [];

+ 0 - 39
editor/js/Menubar.Play.js

@@ -1,39 +0,0 @@
-import { UIPanel } from './libs/ui.js';
-
-function MenubarPlay( editor ) {
-
-	const signals = editor.signals;
-	const strings = editor.strings;
-
-	const container = new UIPanel();
-	container.setClass( 'menu' );
-
-	let isPlaying = false;
-
-	const title = new UIPanel();
-	title.setClass( 'title' );
-	title.setTextContent( strings.getKey( 'menubar/play' ) );
-	title.onClick( function () {
-
-		if ( isPlaying === false ) {
-
-			isPlaying = true;
-			title.setTextContent( strings.getKey( 'menubar/play/stop' ) );
-			signals.startPlayer.dispatch();
-
-		} else {
-
-			isPlaying = false;
-			title.setTextContent( strings.getKey( 'menubar/play/play' ) );
-			signals.stopPlayer.dispatch();
-
-		}
-
-	} );
-	container.add( title );
-
-	return container;
-
-}
-
-export { MenubarPlay };

+ 42 - 12
editor/js/Menubar.View.js

@@ -2,6 +2,7 @@ import { UIPanel, UIRow } from './libs/ui.js';
 
 function MenubarView( editor ) {
 
+	const signals = editor.signals;
 	const strings = editor.strings;
 
 	const container = new UIPanel();
@@ -48,29 +49,58 @@ function MenubarView( editor ) {
 	} );
 	options.add( option );
 
-	// VR (Work in progress)
+	// XR (Work in progress)
 
 	if ( 'xr' in navigator ) {
 
-		navigator.xr.isSessionSupported( 'immersive-vr' )
-			.then( function ( supported ) {
+		if ( 'offerSession' in navigator.xr ) {
 
-				if ( supported ) {
+			signals.offerXR.dispatch( 'immersive-ar' );
 
-					const option = new UIRow();
-					option.setClass( 'option' );
-					option.setTextContent( 'VR' );
-					option.onClick( function () {
+		} else {
 
-						editor.signals.toggleVR.dispatch();
+			navigator.xr.isSessionSupported( 'immersive-ar' )
+				.then( function ( supported ) {
 
-					} );
-					options.add( option );
+					if ( supported ) {
 
-				}
+						const option = new UIRow();
+						option.setClass( 'option' );
+						option.setTextContent( 'AR' );
+						option.onClick( function () {
+
+							signals.enterXR.dispatch( 'immersive-ar' );
+
+						} );
+						options.add( option );
+
+					} else {
+
+						navigator.xr.isSessionSupported( 'immersive-vr' )
+							.then( function ( supported ) {
+
+								if ( supported ) {
+
+									const option = new UIRow();
+									option.setClass( 'option' );
+									option.setTextContent( 'VR' );
+									option.onClick( function () {
+
+										signals.enterXR.dispatch( 'immersive-vr' );
+
+									} );
+									options.add( option );
+
+								}
+
+							} );
+
+					}
 
 			} );
 
+		}
+
 	}
 
 	return container;

+ 0 - 2
editor/js/Menubar.js

@@ -6,7 +6,6 @@ import { MenubarFile } from './Menubar.File.js';
 import { MenubarExamples } from './Menubar.Examples.js';
 import { MenubarView } from './Menubar.View.js';
 import { MenubarHelp } from './Menubar.Help.js';
-import { MenubarPlay } from './Menubar.Play.js';
 import { MenubarStatus } from './Menubar.Status.js';
 
 function Menubar( editor ) {
@@ -17,7 +16,6 @@ function Menubar( editor ) {
 	container.add( new MenubarFile( editor ) );
 	container.add( new MenubarEdit( editor ) );
 	container.add( new MenubarAdd( editor ) );
-	container.add( new MenubarPlay( editor ) );
 	container.add( new MenubarExamples( editor ) );
 	container.add( new MenubarView( editor ) );
 	container.add( new MenubarHelp( editor ) );

+ 35 - 0
editor/js/Viewport.Selector.js → editor/js/Selector.js

@@ -1,3 +1,8 @@
+import * as THREE from 'three';
+
+const mouse = new THREE.Vector2();
+const raycaster = new THREE.Raycaster();
+
 class Selector {
 
 	constructor( editor ) {
@@ -37,6 +42,36 @@ class Selector {
 
 	}
 
+	getIntersects( raycaster ) {
+
+		const objects = [];
+
+		this.editor.scene.traverseVisible( function ( child ) {
+
+			objects.push( child );
+
+		} );
+
+		this.editor.sceneHelpers.traverseVisible( function ( child ) {
+
+			if ( child.name === 'picker' ) objects.push( child );
+
+		} );
+
+		return raycaster.intersectObjects( objects, false );
+
+	}
+
+	getPointerIntersects( point, camera ) {
+
+		mouse.set( ( point.x * 2 ) - 1, - ( point.y * 2 ) + 1 );
+
+		raycaster.setFromCamera( mouse, camera );
+
+		return this.getIntersects( raycaster );
+
+	}
+
 	select( object ) {
 
 		if ( this.editor.selected === object ) return;

+ 9 - 9
editor/js/Sidebar.Geometry.BoxGeometry.js

@@ -16,9 +16,9 @@ function GeometryParametersPanel( editor, object ) {
 	// width
 
 	const widthRow = new UIRow();
-	const width = new UINumber( parameters.width ).onChange( update );
+	const width = new UINumber().setPrecision( 3 ).setValue( parameters.width ).onChange( update );
 
-	widthRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/width' ) ).setWidth( '90px' ) );
+	widthRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/width' ) ).setClass( 'Label' ) );
 	widthRow.add( width );
 
 	container.add( widthRow );
@@ -26,9 +26,9 @@ function GeometryParametersPanel( editor, object ) {
 	// height
 
 	const heightRow = new UIRow();
-	const height = new UINumber( parameters.height ).onChange( update );
+	const height = new UINumber().setPrecision( 3 ).setValue( parameters.height ).onChange( update );
 
-	heightRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/height' ) ).setWidth( '90px' ) );
+	heightRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/height' ) ).setClass( 'Label' ) );
 	heightRow.add( height );
 
 	container.add( heightRow );
@@ -36,9 +36,9 @@ function GeometryParametersPanel( editor, object ) {
 	// depth
 
 	const depthRow = new UIRow();
-	const depth = new UINumber( parameters.depth ).onChange( update );
+	const depth = new UINumber().setPrecision( 3 ).setValue( parameters.depth ).onChange( update );
 
-	depthRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/depth' ) ).setWidth( '90px' ) );
+	depthRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/depth' ) ).setClass( 'Label' ) );
 	depthRow.add( depth );
 
 	container.add( depthRow );
@@ -48,7 +48,7 @@ function GeometryParametersPanel( editor, object ) {
 	const widthSegmentsRow = new UIRow();
 	const widthSegments = new UIInteger( parameters.widthSegments ).setRange( 1, Infinity ).onChange( update );
 
-	widthSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/widthseg' ) ).setWidth( '90px' ) );
+	widthSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/widthseg' ) ).setClass( 'Label' ) );
 	widthSegmentsRow.add( widthSegments );
 
 	container.add( widthSegmentsRow );
@@ -58,7 +58,7 @@ function GeometryParametersPanel( editor, object ) {
 	const heightSegmentsRow = new UIRow();
 	const heightSegments = new UIInteger( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
 
-	heightSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/heightseg' ) ).setWidth( '90px' ) );
+	heightSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/heightseg' ) ).setClass( 'Label' ) );
 	heightSegmentsRow.add( heightSegments );
 
 	container.add( heightSegmentsRow );
@@ -68,7 +68,7 @@ function GeometryParametersPanel( editor, object ) {
 	const depthSegmentsRow = new UIRow();
 	const depthSegments = new UIInteger( parameters.depthSegments ).setRange( 1, Infinity ).onChange( update );
 
-	depthSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/depthseg' ) ).setWidth( '90px' ) );
+	depthSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/box_geometry/depthseg' ) ).setClass( 'Label' ) );
 	depthSegmentsRow.add( depthSegments );
 
 	container.add( depthSegmentsRow );

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

@@ -24,7 +24,7 @@ function SidebarGeometryBufferGeometry( editor ) {
 
 			const attributesRow = new UIRow();
 
-			const textAttributes = new UIText( strings.getKey( 'sidebar/geometry/buffer_geometry/attributes' ) ).setWidth( '90px' );
+			const textAttributes = new UIText( strings.getKey( 'sidebar/geometry/buffer_geometry/attributes' ) ).setClass( 'Label' );
 			attributesRow.add( textAttributes );
 
 			const containerAttributes = new UISpan().setDisplay( 'inline-block' ).setVerticalAlign( 'middle' ).setWidth( '160px' );
@@ -65,7 +65,7 @@ function SidebarGeometryBufferGeometry( editor ) {
 
 				const rowMorphAttributes = new UIRow();
 
-				const textMorphAttributes = new UIText( strings.getKey( 'sidebar/geometry/buffer_geometry/morphAttributes' ) ).setWidth( '90px' );
+				const textMorphAttributes = new UIText( strings.getKey( 'sidebar/geometry/buffer_geometry/morphAttributes' ) ).setClass( 'Label' );
 				rowMorphAttributes.add( textMorphAttributes );
 
 				const containerMorphAttributes = new UISpan().setDisplay( 'inline-block' ).setVerticalAlign( 'middle' ).setWidth( '160px' );
@@ -87,7 +87,7 @@ function SidebarGeometryBufferGeometry( editor ) {
 
 				const rowMorphRelative = new UIRow();
 
-				const textMorphRelative = new UIText( strings.getKey( 'sidebar/geometry/buffer_geometry/morphRelative' ) ).setWidth( '90px' );
+				const textMorphRelative = new UIText( strings.getKey( 'sidebar/geometry/buffer_geometry/morphRelative' ) ).setClass( 'Label' );
 				rowMorphRelative.add( textMorphRelative );
 
 				const checkboxMorphRelative = new UICheckbox().setValue( geometry.morphTargetsRelative ).setDisabled( true );

+ 4 - 4
editor/js/Sidebar.Geometry.CapsuleGeometry.js

@@ -18,7 +18,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radiusRow = new UIRow();
 	const radius = new UINumber( parameters.radius ).onChange( update );
 
-	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/radius' ) ).setWidth( '90px' ) );
+	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/radius' ) ).setClass( 'Label' ) );
 	radiusRow.add( radius );
 
 	container.add( radiusRow );
@@ -28,7 +28,7 @@ function GeometryParametersPanel( editor, object ) {
 	const lengthRow = new UIRow();
 	const length = new UINumber( parameters.length ).onChange( update );
 
-	lengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/length' ) ).setWidth( '90px' ) );
+	lengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/length' ) ).setClass( 'Label' ) );
 	lengthRow.add( length );
 
 	container.add( lengthRow );
@@ -38,7 +38,7 @@ function GeometryParametersPanel( editor, object ) {
 	const capSegmentsRow = new UIRow();
 	const capSegments = new UINumber( parameters.capSegments ).onChange( update );
 
-	capSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/capseg' ) ).setWidth( '90px' ) );
+	capSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/capseg' ) ).setClass( 'Label' ) );
 	capSegmentsRow.add( capSegments );
 
 	container.add( capSegmentsRow );
@@ -48,7 +48,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radialSegmentsRow = new UIRow();
 	const radialSegments = new UIInteger( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
 
-	radialSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/radialseg' ) ).setWidth( '90px' ) );
+	radialSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/capsule_geometry/radialseg' ) ).setClass( 'Label' ) );
 	radialSegmentsRow.add( radialSegments );
 
 	container.add( radialSegmentsRow );

+ 4 - 4
editor/js/Sidebar.Geometry.CircleGeometry.js

@@ -18,7 +18,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radiusRow = new UIRow();
 	const radius = new UINumber( parameters.radius ).onChange( update );
 
-	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/radius' ) ).setWidth( '90px' ) );
+	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/radius' ) ).setClass( 'Label' ) );
 	radiusRow.add( radius );
 
 	container.add( radiusRow );
@@ -28,7 +28,7 @@ function GeometryParametersPanel( editor, object ) {
 	const segmentsRow = new UIRow();
 	const segments = new UIInteger( parameters.segments ).setRange( 3, Infinity ).onChange( update );
 
-	segmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/segments' ) ).setWidth( '90px' ) );
+	segmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/segments' ) ).setClass( 'Label' ) );
 	segmentsRow.add( segments );
 
 	container.add( segmentsRow );
@@ -38,7 +38,7 @@ function GeometryParametersPanel( editor, object ) {
 	const thetaStartRow = new UIRow();
 	const thetaStart = new UINumber( parameters.thetaStart * THREE.MathUtils.RAD2DEG ).setStep( 10 ).onChange( update );
 
-	thetaStartRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/thetastart' ) ).setWidth( '90px' ) );
+	thetaStartRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/thetastart' ) ).setClass( 'Label' ) );
 	thetaStartRow.add( thetaStart );
 
 	container.add( thetaStartRow );
@@ -48,7 +48,7 @@ function GeometryParametersPanel( editor, object ) {
 	const thetaLengthRow = new UIRow();
 	const thetaLength = new UINumber( parameters.thetaLength * THREE.MathUtils.RAD2DEG ).setStep( 10 ).onChange( update );
 
-	thetaLengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/thetalength' ) ).setWidth( '90px' ) );
+	thetaLengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/thetalength' ) ).setClass( 'Label' ) );
 	thetaLengthRow.add( thetaLength );
 
 	container.add( thetaLengthRow );

+ 6 - 6
editor/js/Sidebar.Geometry.CylinderGeometry.js

@@ -18,7 +18,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radiusTopRow = new UIRow();
 	const radiusTop = new UINumber( parameters.radiusTop ).onChange( update );
 
-	radiusTopRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/radiustop' ) ).setWidth( '90px' ) );
+	radiusTopRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/radiustop' ) ).setClass( 'Label' ) );
 	radiusTopRow.add( radiusTop );
 
 	container.add( radiusTopRow );
@@ -28,7 +28,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radiusBottomRow = new UIRow();
 	const radiusBottom = new UINumber( parameters.radiusBottom ).onChange( update );
 
-	radiusBottomRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/radiusbottom' ) ).setWidth( '90px' ) );
+	radiusBottomRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/radiusbottom' ) ).setClass( 'Label' ) );
 	radiusBottomRow.add( radiusBottom );
 
 	container.add( radiusBottomRow );
@@ -38,7 +38,7 @@ function GeometryParametersPanel( editor, object ) {
 	const heightRow = new UIRow();
 	const height = new UINumber( parameters.height ).onChange( update );
 
-	heightRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/height' ) ).setWidth( '90px' ) );
+	heightRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/height' ) ).setClass( 'Label' ) );
 	heightRow.add( height );
 
 	container.add( heightRow );
@@ -48,7 +48,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radialSegmentsRow = new UIRow();
 	const radialSegments = new UIInteger( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
 
-	radialSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/radialsegments' ) ).setWidth( '90px' ) );
+	radialSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/radialsegments' ) ).setClass( 'Label' ) );
 	radialSegmentsRow.add( radialSegments );
 
 	container.add( radialSegmentsRow );
@@ -58,7 +58,7 @@ function GeometryParametersPanel( editor, object ) {
 	const heightSegmentsRow = new UIRow();
 	const heightSegments = new UIInteger( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
 
-	heightSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/heightsegments' ) ).setWidth( '90px' ) );
+	heightSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/heightsegments' ) ).setClass( 'Label' ) );
 	heightSegmentsRow.add( heightSegments );
 
 	container.add( heightSegmentsRow );
@@ -68,7 +68,7 @@ function GeometryParametersPanel( editor, object ) {
 	const openEndedRow = new UIRow();
 	const openEnded = new UICheckbox( parameters.openEnded ).onChange( update );
 
-	openEndedRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/openended' ) ).setWidth( '90px' ) );
+	openEndedRow.add( new UIText( strings.getKey( 'sidebar/geometry/cylinder_geometry/openended' ) ).setClass( 'Label' ) );
 	openEndedRow.add( openEnded );
 
 	container.add( openEndedRow );

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

@@ -18,7 +18,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radiusRow = new UIRow();
 	const radius = new UINumber( parameters.radius ).onChange( update );
 
-	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/dodecahedron_geometry/radius' ) ).setWidth( '90px' ) );
+	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/dodecahedron_geometry/radius' ) ).setClass( 'Label' ) );
 	radiusRow.add( radius );
 
 	container.add( radiusRow );
@@ -28,7 +28,7 @@ function GeometryParametersPanel( editor, object ) {
 	const detailRow = new UIRow();
 	const detail = new UIInteger( parameters.detail ).setRange( 0, Infinity ).onChange( update );
 
-	detailRow.add( new UIText( strings.getKey( 'sidebar/geometry/dodecahedron_geometry/detail' ) ).setWidth( '90px' ) );
+	detailRow.add( new UIText( strings.getKey( 'sidebar/geometry/dodecahedron_geometry/detail' ) ).setClass( 'Label' ) );
 	detailRow.add( detail );
 
 	container.add( detailRow );

+ 9 - 9
editor/js/Sidebar.Geometry.ExtrudeGeometry.js

@@ -27,7 +27,7 @@ function GeometryParametersPanel( editor, object ) {
 	const curveSegmentsRow = new UIRow();
 	const curveSegments = new UIInteger( options.curveSegments ).onChange( update ).setRange( 1, Infinity );
 
-	curveSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/curveSegments' ) ).setWidth( '90px' ) );
+	curveSegmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/curveSegments' ) ).setClass( 'Label' ) );
 	curveSegmentsRow.add( curveSegments );
 
 	container.add( curveSegmentsRow );
@@ -37,7 +37,7 @@ function GeometryParametersPanel( editor, object ) {
 	const stepsRow = new UIRow();
 	const steps = new UIInteger( options.steps ).onChange( update ).setRange( 1, Infinity );
 
-	stepsRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/steps' ) ).setWidth( '90px' ) );
+	stepsRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/steps' ) ).setClass( 'Label' ) );
 	stepsRow.add( steps );
 
 	container.add( stepsRow );
@@ -47,7 +47,7 @@ function GeometryParametersPanel( editor, object ) {
 	const depthRow = new UIRow();
 	const depth = new UINumber( options.depth ).onChange( update ).setRange( 1, Infinity );
 
-	depthRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/depth' ) ).setWidth( '90px' ) );
+	depthRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/depth' ) ).setClass( 'Label' ) );
 	depthRow.add( depth );
 
 	container.add( depthRow );
@@ -57,7 +57,7 @@ function GeometryParametersPanel( editor, object ) {
 	const enabledRow = new UIRow();
 	const enabled = new UICheckbox( options.bevelEnabled ).onChange( update );
 
-	enabledRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelEnabled' ) ).setWidth( '90px' ) );
+	enabledRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelEnabled' ) ).setClass( 'Label' ) );
 	enabledRow.add( enabled );
 
 	container.add( enabledRow );
@@ -71,7 +71,7 @@ function GeometryParametersPanel( editor, object ) {
 		const thicknessRow = new UIRow();
 		thickness = new UINumber( options.bevelThickness ).onChange( update );
 
-		thicknessRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelThickness' ) ).setWidth( '90px' ) );
+		thicknessRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelThickness' ) ).setClass( 'Label' ) );
 		thicknessRow.add( thickness );
 
 		container.add( thicknessRow );
@@ -81,7 +81,7 @@ function GeometryParametersPanel( editor, object ) {
 		const sizeRow = new UIRow();
 		size = new UINumber( options.bevelSize ).onChange( update );
 
-		sizeRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelSize' ) ).setWidth( '90px' ) );
+		sizeRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelSize' ) ).setClass( 'Label' ) );
 		sizeRow.add( size );
 
 		container.add( sizeRow );
@@ -91,7 +91,7 @@ function GeometryParametersPanel( editor, object ) {
 		const offsetRow = new UIRow();
 		offset = new UINumber( options.bevelOffset ).onChange( update );
 
-		offsetRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelOffset' ) ).setWidth( '90px' ) );
+		offsetRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelOffset' ) ).setClass( 'Label' ) );
 		offsetRow.add( offset );
 
 		container.add( offsetRow );
@@ -101,14 +101,14 @@ function GeometryParametersPanel( editor, object ) {
 		const segmentsRow = new UIRow();
 		segments = new UIInteger( options.bevelSegments ).onChange( update ).setRange( 0, Infinity );
 
-		segmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelSegments' ) ).setWidth( '90px' ) );
+		segmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/extrude_geometry/bevelSegments' ) ).setClass( 'Label' ) );
 		segmentsRow.add( segments );
 
 		container.add( segmentsRow );
 
 	}
 
-	const button = new UIButton( strings.getKey( 'sidebar/geometry/extrude_geometry/shape' ) ).onClick( toShape ).setWidth( '90px' ).setMarginLeft( '90px' );
+	const button = new UIButton( strings.getKey( 'sidebar/geometry/extrude_geometry/shape' ) ).onClick( toShape ).setClass( 'Label' ).setMarginLeft( '120px' );
 	container.add( button );
 
 	//

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

@@ -20,7 +20,7 @@ function GeometryParametersPanel( editor, object ) {
 	const radiusRow = new UIRow();
 	const radius = new UINumber( parameters.radius ).onChange( update );
 
-	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/icosahedron_geometry/radius' ) ).setWidth( '90px' ) );
+	radiusRow.add( new UIText( strings.getKey( 'sidebar/geometry/icosahedron_geometry/radius' ) ).setClass( 'Label' ) );
 	radiusRow.add( radius );
 
 	container.add( radiusRow );
@@ -30,7 +30,7 @@ function GeometryParametersPanel( editor, object ) {
 	const detailRow = new UIRow();
 	const detail = new UIInteger( parameters.detail ).setRange( 0, Infinity ).onChange( update );
 
-	detailRow.add( new UIText( strings.getKey( 'sidebar/geometry/icosahedron_geometry/detail' ) ).setWidth( '90px' ) );
+	detailRow.add( new UIText( strings.getKey( 'sidebar/geometry/icosahedron_geometry/detail' ) ).setClass( 'Label' ) );
 	detailRow.add( detail );
 
 	container.add( detailRow );

+ 4 - 4
editor/js/Sidebar.Geometry.LatheGeometry.js

@@ -19,7 +19,7 @@ function GeometryParametersPanel( editor, object ) {
 	const segmentsRow = new UIRow();
 	const segments = new UIInteger( parameters.segments ).onChange( update );
 
-	segmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/segments' ) ).setWidth( '90px' ) );
+	segmentsRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/segments' ) ).setClass( 'Label' ) );
 	segmentsRow.add( segments );
 
 	container.add( segmentsRow );
@@ -29,7 +29,7 @@ function GeometryParametersPanel( editor, object ) {
 	const phiStartRow = new UIRow();
 	const phiStart = new UINumber( parameters.phiStart * 180 / Math.PI ).onChange( update );
 
-	phiStartRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/phistart' ) ).setWidth( '90px' ) );
+	phiStartRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/phistart' ) ).setClass( 'Label' ) );
 	phiStartRow.add( phiStart );
 
 	container.add( phiStartRow );
@@ -39,7 +39,7 @@ function GeometryParametersPanel( editor, object ) {
 	const phiLengthRow = new UIRow();
 	const phiLength = new UINumber( parameters.phiLength * 180 / Math.PI ).onChange( update );
 
-	phiLengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/philength' ) ).setWidth( '90px' ) );
+	phiLengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/philength' ) ).setClass( 'Label' ) );
 	phiLengthRow.add( phiLength );
 
 	container.add( phiLengthRow );
@@ -47,7 +47,7 @@ function GeometryParametersPanel( editor, object ) {
 	// points
 
 	const pointsRow = new UIRow();
-	pointsRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/points' ) ).setWidth( '90px' ) );
+	pointsRow.add( new UIText( strings.getKey( 'sidebar/geometry/lathe_geometry/points' ) ).setClass( 'Label' ) );
 
 	const points = new UIPoints2().setValue( parameters.points ).onChange( update );
 	pointsRow.add( points );

Some files were not shown because too many files changed in this diff