three-render-objects 1.28.5 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,6 +48,7 @@ ThreeRenderObjects({ configOptions })(<domElement>)
48
48
  | Method | Description | Default |
49
49
  | --- | --- | :--: |
50
50
  | <b>objects</b>([<i>array</i>]) | Getter/setter for the list of objects to render. Each object should be an instance of [Object3D](https://threejs.org/docs/#api/core/Object3D). | `[]` |
51
+ | <b>lights</b>([<i>array</i>]) | Getter/setter for the list of lights to use in the scene. Each item should be an instance of [Light](https://threejs.org/docs/#api/en/lights/Light). | `[]` |
51
52
 
52
53
  ### Container layout
53
54
 
@@ -1,4 +1,4 @@
1
- import { WebGLRendererParameters, Renderer, Object3D, WebGLRenderer, Scene, Camera, Intersection } from 'three';
1
+ import { WebGLRendererParameters, Renderer, Object3D, Light, WebGLRenderer, Scene, Camera, Intersection } from 'three';
2
2
  import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js';
3
3
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
4
4
  import { FlyControls } from 'three/examples/jsm/controls/FlyControls.js';
@@ -25,6 +25,8 @@ interface ThreeRenderObjectsGenericInstance<ChainableInstance> {
25
25
  // Data input
26
26
  objects(): Object3D[];
27
27
  objects(objs: Object3D[]): ChainableInstance;
28
+ lights(): Light[];
29
+ lights(lights: Light[]): ChainableInstance;
28
30
 
29
31
  // Container layout
30
32
  width(): number;
@@ -84,4 +86,4 @@ type ThreeRenderObjectsInstance = ThreeRenderObjectsGenericInstance<ThreeRenderO
84
86
 
85
87
  declare function ThreeRenderObjects(configOptions?: ConfigOptions): ThreeRenderObjectsInstance;
86
88
 
87
- export { ConfigOptions, ThreeRenderObjectsGenericInstance, ThreeRenderObjectsInstance, ThreeRenderObjects as default };
89
+ export { type ConfigOptions, type ThreeRenderObjectsGenericInstance, type ThreeRenderObjectsInstance, ThreeRenderObjects as default };
@@ -1,4 +1,4 @@
1
- // Version 1.28.5 three-render-objects - https://github.com/vasturiano/three-render-objects
1
+ // Version 1.29.0 three-render-objects - https://github.com/vasturiano/three-render-objects
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('three')) :
4
4
  typeof define === 'function' && define.amd ? define(['three'], factory) :
@@ -32,34 +32,34 @@
32
32
  }
33
33
  }
34
34
 
35
- var css_248z = ".scene-nav-info {\n bottom: 5px;\n width: 100%;\n text-align: center;\n color: slategrey;\n opacity: 0.7;\n font-size: 10px;\n}\n\n.scene-tooltip {\n top: 0;\n color: lavender;\n font-size: 15px;\n}\n\n.scene-nav-info, .scene-tooltip {\n position: absolute;\n font-family: sans-serif;\n pointer-events: none;\n}\n\n.scene-container canvas:focus {\n outline: none;\n}";
35
+ var css_248z = ".scene-nav-info {\n bottom: 5px;\n width: 100%;\n text-align: center;\n color: slategrey;\n opacity: 0.7;\n font-size: 10px;\n}\n\n.scene-tooltip {\n top: 0;\n color: lavender;\n font-size: 15px;\n}\n\n.scene-nav-info, .scene-tooltip {\n position: absolute;\n font-family: sans-serif;\n pointer-events: none;\n user-select: none;\n}\n\n.scene-container canvas:focus {\n outline: none;\n}";
36
36
  styleInject(css_248z);
37
37
 
38
- function _iterableToArrayLimit$1(arr, i) {
39
- var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"];
40
- if (null != _i) {
41
- var _s,
42
- _e,
43
- _x,
44
- _r,
45
- _arr = [],
46
- _n = !0,
47
- _d = !1;
38
+ function _iterableToArrayLimit$1(r, l) {
39
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
40
+ if (null != t) {
41
+ var e,
42
+ n,
43
+ i,
44
+ u,
45
+ a = [],
46
+ f = !0,
47
+ o = !1;
48
48
  try {
49
- if (_x = (_i = _i.call(arr)).next, 0 === i) {
50
- if (Object(_i) !== _i) return;
51
- _n = !1;
52
- } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
53
- } catch (err) {
54
- _d = !0, _e = err;
49
+ if (i = (t = t.call(r)).next, 0 === l) {
50
+ if (Object(t) !== t) return;
51
+ f = !1;
52
+ } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
53
+ } catch (r) {
54
+ o = !0, n = r;
55
55
  } finally {
56
56
  try {
57
- if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return;
57
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
58
58
  } finally {
59
- if (_d) throw _e;
59
+ if (o) throw n;
60
60
  }
61
61
  }
62
- return _arr;
62
+ return a;
63
63
  }
64
64
  }
65
65
  function _defineProperty(obj, key, value) {
@@ -953,6 +953,9 @@
953
953
  const _changeEvent$1 = { type: 'change' };
954
954
  const _startEvent = { type: 'start' };
955
955
  const _endEvent = { type: 'end' };
956
+ const _ray = new three$1.Ray();
957
+ const _plane = new three$1.Plane();
958
+ const TILT_LIMIT = Math.cos( 70 * three$1.MathUtils.DEG2RAD );
956
959
 
957
960
  class OrbitControls extends three$1.EventDispatcher {
958
961
 
@@ -1007,6 +1010,7 @@
1007
1010
  this.panSpeed = 1.0;
1008
1011
  this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
1009
1012
  this.keyPanSpeed = 7.0; // pixels moved per arrow key push
1013
+ this.zoomToCursor = false;
1010
1014
 
1011
1015
  // Set to true to automatically rotate around the target
1012
1016
  // If auto-rotate is enabled, you must call controls.update() in your animation loop
@@ -1104,7 +1108,7 @@
1104
1108
 
1105
1109
  const twoPI = 2 * Math.PI;
1106
1110
 
1107
- return function update() {
1111
+ return function update( deltaTime = null ) {
1108
1112
 
1109
1113
  const position = scope.object.position;
1110
1114
 
@@ -1118,7 +1122,7 @@
1118
1122
 
1119
1123
  if ( scope.autoRotate && state === STATE.NONE ) {
1120
1124
 
1121
- rotateLeft( getAutoRotationAngle() );
1125
+ rotateLeft( getAutoRotationAngle( deltaTime ) );
1122
1126
 
1123
1127
  }
1124
1128
 
@@ -1165,11 +1169,6 @@
1165
1169
  spherical.makeSafe();
1166
1170
 
1167
1171
 
1168
- spherical.radius *= scale;
1169
-
1170
- // restrict radius to be between desired limits
1171
- spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
1172
-
1173
1172
  // move target to panned location
1174
1173
 
1175
1174
  if ( scope.enableDamping === true ) {
@@ -1182,6 +1181,19 @@
1182
1181
 
1183
1182
  }
1184
1183
 
1184
+ // adjust the camera position based on zoom only if we're not zooming to the cursor or if it's an ortho camera
1185
+ // we adjust zoom later in these cases
1186
+ if ( scope.zoomToCursor && performCursorZoom || scope.object.isOrthographicCamera ) {
1187
+
1188
+ spherical.radius = clampDistance( spherical.radius );
1189
+
1190
+ } else {
1191
+
1192
+ spherical.radius = clampDistance( spherical.radius * scale );
1193
+
1194
+ }
1195
+
1196
+
1185
1197
  offset.setFromSpherical( spherical );
1186
1198
 
1187
1199
  // rotate offset back to "camera-up-vector-is-up" space
@@ -1206,7 +1218,91 @@
1206
1218
 
1207
1219
  }
1208
1220
 
1221
+ // adjust camera position
1222
+ let zoomChanged = false;
1223
+ if ( scope.zoomToCursor && performCursorZoom ) {
1224
+
1225
+ let newRadius = null;
1226
+ if ( scope.object.isPerspectiveCamera ) {
1227
+
1228
+ // move the camera down the pointer ray
1229
+ // this method avoids floating point error
1230
+ const prevRadius = offset.length();
1231
+ newRadius = clampDistance( prevRadius * scale );
1232
+
1233
+ const radiusDelta = prevRadius - newRadius;
1234
+ scope.object.position.addScaledVector( dollyDirection, radiusDelta );
1235
+ scope.object.updateMatrixWorld();
1236
+
1237
+ } else if ( scope.object.isOrthographicCamera ) {
1238
+
1239
+ // adjust the ortho camera position based on zoom changes
1240
+ const mouseBefore = new three$1.Vector3( mouse.x, mouse.y, 0 );
1241
+ mouseBefore.unproject( scope.object );
1242
+
1243
+ scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
1244
+ scope.object.updateProjectionMatrix();
1245
+ zoomChanged = true;
1246
+
1247
+ const mouseAfter = new three$1.Vector3( mouse.x, mouse.y, 0 );
1248
+ mouseAfter.unproject( scope.object );
1249
+
1250
+ scope.object.position.sub( mouseAfter ).add( mouseBefore );
1251
+ scope.object.updateMatrixWorld();
1252
+
1253
+ newRadius = offset.length();
1254
+
1255
+ } else {
1256
+
1257
+ console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.' );
1258
+ scope.zoomToCursor = false;
1259
+
1260
+ }
1261
+
1262
+ // handle the placement of the target
1263
+ if ( newRadius !== null ) {
1264
+
1265
+ if ( this.screenSpacePanning ) {
1266
+
1267
+ // position the orbit target in front of the new camera position
1268
+ scope.target.set( 0, 0, - 1 )
1269
+ .transformDirection( scope.object.matrix )
1270
+ .multiplyScalar( newRadius )
1271
+ .add( scope.object.position );
1272
+
1273
+ } else {
1274
+
1275
+ // get the ray and translation plane to compute target
1276
+ _ray.origin.copy( scope.object.position );
1277
+ _ray.direction.set( 0, 0, - 1 ).transformDirection( scope.object.matrix );
1278
+
1279
+ // if the camera is 20 degrees above the horizon then don't adjust the focus target to avoid
1280
+ // extremely large values
1281
+ if ( Math.abs( scope.object.up.dot( _ray.direction ) ) < TILT_LIMIT ) {
1282
+
1283
+ object.lookAt( scope.target );
1284
+
1285
+ } else {
1286
+
1287
+ _plane.setFromNormalAndCoplanarPoint( scope.object.up, scope.target );
1288
+ _ray.intersectPlane( _plane, scope.target );
1289
+
1290
+ }
1291
+
1292
+ }
1293
+
1294
+ }
1295
+
1296
+ } else if ( scope.object.isOrthographicCamera ) {
1297
+
1298
+ scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
1299
+ scope.object.updateProjectionMatrix();
1300
+ zoomChanged = true;
1301
+
1302
+ }
1303
+
1209
1304
  scale = 1;
1305
+ performCursorZoom = false;
1210
1306
 
1211
1307
  // update condition is:
1212
1308
  // min(camera displacement, camera rotation in radians)^2 > EPS
@@ -1285,7 +1381,6 @@
1285
1381
 
1286
1382
  let scale = 1;
1287
1383
  const panOffset = new three$1.Vector3();
1288
- let zoomChanged = false;
1289
1384
 
1290
1385
  const rotateStart = new three$1.Vector2();
1291
1386
  const rotateEnd = new three$1.Vector2();
@@ -1299,12 +1394,24 @@
1299
1394
  const dollyEnd = new three$1.Vector2();
1300
1395
  const dollyDelta = new three$1.Vector2();
1301
1396
 
1397
+ const dollyDirection = new three$1.Vector3();
1398
+ const mouse = new three$1.Vector2();
1399
+ let performCursorZoom = false;
1400
+
1302
1401
  const pointers = [];
1303
1402
  const pointerPositions = {};
1304
1403
 
1305
- function getAutoRotationAngle() {
1404
+ function getAutoRotationAngle( deltaTime ) {
1405
+
1406
+ if ( deltaTime !== null ) {
1306
1407
 
1307
- return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
1408
+ return ( 2 * Math.PI / 60 * scope.autoRotateSpeed ) * deltaTime;
1409
+
1410
+ } else {
1411
+
1412
+ return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
1413
+
1414
+ }
1308
1415
 
1309
1416
  }
1310
1417
 
@@ -1409,16 +1516,10 @@
1409
1516
 
1410
1517
  function dollyOut( dollyScale ) {
1411
1518
 
1412
- if ( scope.object.isPerspectiveCamera ) {
1519
+ if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {
1413
1520
 
1414
1521
  scale /= dollyScale;
1415
1522
 
1416
- } else if ( scope.object.isOrthographicCamera ) {
1417
-
1418
- scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
1419
- scope.object.updateProjectionMatrix();
1420
- zoomChanged = true;
1421
-
1422
1523
  } else {
1423
1524
 
1424
1525
  console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
@@ -1430,16 +1531,10 @@
1430
1531
 
1431
1532
  function dollyIn( dollyScale ) {
1432
1533
 
1433
- if ( scope.object.isPerspectiveCamera ) {
1534
+ if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {
1434
1535
 
1435
1536
  scale *= dollyScale;
1436
1537
 
1437
- } else if ( scope.object.isOrthographicCamera ) {
1438
-
1439
- scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
1440
- scope.object.updateProjectionMatrix();
1441
- zoomChanged = true;
1442
-
1443
1538
  } else {
1444
1539
 
1445
1540
  console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
@@ -1449,6 +1544,35 @@
1449
1544
 
1450
1545
  }
1451
1546
 
1547
+ function updateMouseParameters( event ) {
1548
+
1549
+ if ( ! scope.zoomToCursor ) {
1550
+
1551
+ return;
1552
+
1553
+ }
1554
+
1555
+ performCursorZoom = true;
1556
+
1557
+ const rect = scope.domElement.getBoundingClientRect();
1558
+ const x = event.clientX - rect.left;
1559
+ const y = event.clientY - rect.top;
1560
+ const w = rect.width;
1561
+ const h = rect.height;
1562
+
1563
+ mouse.x = ( x / w ) * 2 - 1;
1564
+ mouse.y = - ( y / h ) * 2 + 1;
1565
+
1566
+ dollyDirection.set( mouse.x, mouse.y, 1 ).unproject( scope.object ).sub( scope.object.position ).normalize();
1567
+
1568
+ }
1569
+
1570
+ function clampDistance( dist ) {
1571
+
1572
+ return Math.max( scope.minDistance, Math.min( scope.maxDistance, dist ) );
1573
+
1574
+ }
1575
+
1452
1576
  //
1453
1577
  // event callbacks - update the object state
1454
1578
  //
@@ -1461,6 +1585,7 @@
1461
1585
 
1462
1586
  function handleMouseDownDolly( event ) {
1463
1587
 
1588
+ updateMouseParameters( event );
1464
1589
  dollyStart.set( event.clientX, event.clientY );
1465
1590
 
1466
1591
  }
@@ -1527,6 +1652,8 @@
1527
1652
 
1528
1653
  function handleMouseWheel( event ) {
1529
1654
 
1655
+ updateMouseParameters( event );
1656
+
1530
1657
  if ( event.deltaY < 0 ) {
1531
1658
 
1532
1659
  dollyIn( getZoomScale() );
@@ -2211,6 +2338,9 @@
2211
2338
 
2212
2339
  // API
2213
2340
 
2341
+ // Set to false to disable this control
2342
+ this.enabled = true;
2343
+
2214
2344
  this.movementSpeed = 1.0;
2215
2345
  this.rollSpeed = 0.005;
2216
2346
 
@@ -2238,7 +2368,7 @@
2238
2368
 
2239
2369
  this.keydown = function ( event ) {
2240
2370
 
2241
- if ( event.altKey ) {
2371
+ if ( event.altKey || this.enabled === false ) {
2242
2372
 
2243
2373
  return;
2244
2374
 
@@ -2276,6 +2406,8 @@
2276
2406
 
2277
2407
  this.keyup = function ( event ) {
2278
2408
 
2409
+ if ( this.enabled === false ) return;
2410
+
2279
2411
  switch ( event.code ) {
2280
2412
 
2281
2413
  case 'ShiftLeft':
@@ -2308,6 +2440,8 @@
2308
2440
 
2309
2441
  this.pointerdown = function ( event ) {
2310
2442
 
2443
+ if ( this.enabled === false ) return;
2444
+
2311
2445
  if ( this.dragToLook ) {
2312
2446
 
2313
2447
  this.status ++;
@@ -2329,6 +2463,8 @@
2329
2463
 
2330
2464
  this.pointermove = function ( event ) {
2331
2465
 
2466
+ if ( this.enabled === false ) return;
2467
+
2332
2468
  if ( ! this.dragToLook || this.status > 0 ) {
2333
2469
 
2334
2470
  const container = this.getContainerDimensions();
@@ -2346,6 +2482,8 @@
2346
2482
 
2347
2483
  this.pointerup = function ( event ) {
2348
2484
 
2485
+ if ( this.enabled === false ) return;
2486
+
2349
2487
  if ( this.dragToLook ) {
2350
2488
 
2351
2489
  this.status --;
@@ -2369,8 +2507,18 @@
2369
2507
 
2370
2508
  };
2371
2509
 
2510
+ this.contextMenu = function ( event ) {
2511
+
2512
+ if ( this.enabled === false ) return;
2513
+
2514
+ event.preventDefault();
2515
+
2516
+ };
2517
+
2372
2518
  this.update = function ( delta ) {
2373
2519
 
2520
+ if ( this.enabled === false ) return;
2521
+
2374
2522
  const moveMult = delta * scope.movementSpeed;
2375
2523
  const rotMult = delta * scope.rollSpeed;
2376
2524
 
@@ -2438,7 +2586,7 @@
2438
2586
 
2439
2587
  this.dispose = function () {
2440
2588
 
2441
- this.domElement.removeEventListener( 'contextmenu', contextmenu );
2589
+ this.domElement.removeEventListener( 'contextmenu', _contextmenu );
2442
2590
  this.domElement.removeEventListener( 'pointerdown', _pointerdown );
2443
2591
  this.domElement.removeEventListener( 'pointermove', _pointermove );
2444
2592
  this.domElement.removeEventListener( 'pointerup', _pointerup );
@@ -2448,13 +2596,14 @@
2448
2596
 
2449
2597
  };
2450
2598
 
2599
+ const _contextmenu = this.contextMenu.bind( this );
2451
2600
  const _pointermove = this.pointermove.bind( this );
2452
2601
  const _pointerdown = this.pointerdown.bind( this );
2453
2602
  const _pointerup = this.pointerup.bind( this );
2454
2603
  const _keydown = this.keydown.bind( this );
2455
2604
  const _keyup = this.keyup.bind( this );
2456
2605
 
2457
- this.domElement.addEventListener( 'contextmenu', contextmenu );
2606
+ this.domElement.addEventListener( 'contextmenu', _contextmenu );
2458
2607
  this.domElement.addEventListener( 'pointerdown', _pointerdown );
2459
2608
  this.domElement.addEventListener( 'pointermove', _pointermove );
2460
2609
  this.domElement.addEventListener( 'pointerup', _pointerup );
@@ -2469,12 +2618,6 @@
2469
2618
 
2470
2619
  }
2471
2620
 
2472
- function contextmenu( event ) {
2473
-
2474
- event.preventDefault();
2475
-
2476
- }
2477
-
2478
2621
  /**
2479
2622
  * Full-screen textured quad shader
2480
2623
  */
@@ -2511,8 +2654,8 @@
2511
2654
 
2512
2655
  void main() {
2513
2656
 
2514
- gl_FragColor = texture2D( tDiffuse, vUv );
2515
- gl_FragColor.a *= opacity;
2657
+ vec4 texel = texture2D( tDiffuse, vUv );
2658
+ gl_FragColor = opacity * texel;
2516
2659
 
2517
2660
 
2518
2661
  }`
@@ -2728,11 +2871,14 @@
2728
2871
  if ( this.clear ) renderer.clear();
2729
2872
  renderer.render( this.scene, this.camera );
2730
2873
 
2731
- // unlock color and depth buffer for subsequent rendering
2874
+ // unlock color and depth buffer and make them writable for subsequent rendering/clearing
2732
2875
 
2733
2876
  state.buffers.color.setLocked( false );
2734
2877
  state.buffers.depth.setLocked( false );
2735
2878
 
2879
+ state.buffers.color.setMask( true );
2880
+ state.buffers.depth.setMask( true );
2881
+
2736
2882
  // only render where stencil is set to 1
2737
2883
 
2738
2884
  state.buffers.stencil.setLocked( false );
@@ -2799,6 +2945,7 @@
2799
2945
  this.passes = [];
2800
2946
 
2801
2947
  this.copyPass = new ShaderPass( CopyShader );
2948
+ this.copyPass.material.blending = three$1.NoBlending;
2802
2949
 
2803
2950
  this.clock = new three$1.Clock();
2804
2951
 
@@ -2982,7 +3129,7 @@
2982
3129
 
2983
3130
  class RenderPass extends Pass {
2984
3131
 
2985
- constructor( scene, camera, overrideMaterial, clearColor, clearAlpha ) {
3132
+ constructor( scene, camera, overrideMaterial = null, clearColor = null, clearAlpha = null ) {
2986
3133
 
2987
3134
  super();
2988
3135
 
@@ -2992,7 +3139,7 @@
2992
3139
  this.overrideMaterial = overrideMaterial;
2993
3140
 
2994
3141
  this.clearColor = clearColor;
2995
- this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;
3142
+ this.clearAlpha = clearAlpha;
2996
3143
 
2997
3144
  this.clear = true;
2998
3145
  this.clearDepth = false;
@@ -3008,7 +3155,7 @@
3008
3155
 
3009
3156
  let oldClearAlpha, oldOverrideMaterial;
3010
3157
 
3011
- if ( this.overrideMaterial !== undefined ) {
3158
+ if ( this.overrideMaterial !== null ) {
3012
3159
 
3013
3160
  oldOverrideMaterial = this.scene.overrideMaterial;
3014
3161
 
@@ -3016,16 +3163,21 @@
3016
3163
 
3017
3164
  }
3018
3165
 
3019
- if ( this.clearColor ) {
3166
+ if ( this.clearColor !== null ) {
3020
3167
 
3021
3168
  renderer.getClearColor( this._oldClearColor );
3022
- oldClearAlpha = renderer.getClearAlpha();
3169
+ renderer.setClearColor( this.clearColor );
3170
+
3171
+ }
3023
3172
 
3024
- renderer.setClearColor( this.clearColor, this.clearAlpha );
3173
+ if ( this.clearAlpha !== null ) {
3174
+
3175
+ oldClearAlpha = renderer.getClearAlpha();
3176
+ renderer.setClearAlpha( this.clearAlpha );
3025
3177
 
3026
3178
  }
3027
3179
 
3028
- if ( this.clearDepth ) {
3180
+ if ( this.clearDepth == true ) {
3029
3181
 
3030
3182
  renderer.clearDepth();
3031
3183
 
@@ -3033,17 +3185,30 @@
3033
3185
 
3034
3186
  renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
3035
3187
 
3036
- // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
3037
- if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
3188
+ if ( this.clear === true ) {
3189
+
3190
+ // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600
3191
+ renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
3192
+
3193
+ }
3194
+
3038
3195
  renderer.render( this.scene, this.camera );
3039
3196
 
3040
- if ( this.clearColor ) {
3197
+ // restore
3041
3198
 
3042
- renderer.setClearColor( this._oldClearColor, oldClearAlpha );
3199
+ if ( this.clearColor !== null ) {
3200
+
3201
+ renderer.setClearColor( this._oldClearColor );
3043
3202
 
3044
3203
  }
3045
3204
 
3046
- if ( this.overrideMaterial !== undefined ) {
3205
+ if ( this.clearAlpha !== null ) {
3206
+
3207
+ renderer.setClearAlpha( oldClearAlpha );
3208
+
3209
+ }
3210
+
3211
+ if ( this.overrideMaterial !== null ) {
3047
3212
 
3048
3213
  this.scene.overrideMaterial = oldOverrideMaterial;
3049
3214
 
@@ -3099,7 +3264,11 @@
3099
3264
  }
3100
3265
 
3101
3266
  function _isNativeFunction(fn) {
3102
- return Function.toString.call(fn).indexOf("[native code]") !== -1;
3267
+ try {
3268
+ return Function.toString.call(fn).indexOf("[native code]") !== -1;
3269
+ } catch (e) {
3270
+ return typeof fn === "function";
3271
+ }
3103
3272
  }
3104
3273
 
3105
3274
  function _isNativeReflectConstruct() {
@@ -5403,6 +5572,9 @@
5403
5572
  objects: {
5404
5573
  "default": []
5405
5574
  },
5575
+ lights: {
5576
+ "default": []
5577
+ },
5406
5578
  enablePointerInteraction: {
5407
5579
  "default": true,
5408
5580
  onChange: function onChange(_, state) {
@@ -5863,6 +6035,15 @@
5863
6035
  }
5864
6036
  }
5865
6037
  changedProps.hasOwnProperty('showNavInfo') && (state.navInfo.style.display = state.showNavInfo ? null : 'none');
6038
+ if (changedProps.hasOwnProperty('lights')) {
6039
+ (changedProps.lights || []).forEach(function (light) {
6040
+ return state.scene.remove(light);
6041
+ }); // Clear the place
6042
+ state.lights.forEach(function (light) {
6043
+ return state.scene.add(light);
6044
+ }); // Add to scene
6045
+ }
6046
+
5866
6047
  if (changedProps.hasOwnProperty('objects')) {
5867
6048
  (changedProps.objects || []).forEach(function (obj) {
5868
6049
  return state.scene.remove(obj);