@react-three/fiber 7.0.16 → 7.0.20

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.
@@ -1,7 +1,6 @@
1
1
  import * as THREE from 'three';
2
2
  import * as React from 'react';
3
3
  import create from 'zustand';
4
- import shallow from 'zustand/shallow';
5
4
  import Reconciler from 'react-reconciler';
6
5
  import { unstable_now, unstable_runWithPriority, unstable_IdlePriority } from 'scheduler';
7
6
  import { useAsset } from 'use-asset';
@@ -42,6 +41,23 @@ const is = {
42
41
  function makeId(event) {
43
42
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
44
43
  }
44
+ /** Release pointer captures.
45
+ * This is called by releasePointerCapture in the API, and when an object is removed.
46
+ */
47
+
48
+
49
+ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
50
+ const captureData = captures.get(obj);
51
+
52
+ if (captureData) {
53
+ captures.delete(obj); // If this was the last capturing object for this pointer
54
+
55
+ if (captures.size === 0) {
56
+ capturedMap.delete(pointerId);
57
+ captureData.target.releasePointerCapture(pointerId);
58
+ }
59
+ }
60
+ }
45
61
 
46
62
  function removeInteractivity(store, object) {
47
63
  const {
@@ -55,6 +71,9 @@ function removeInteractivity(store, object) {
55
71
  internal.hovered.delete(key);
56
72
  }
57
73
  });
74
+ internal.capturedMap.forEach((captures, pointerId) => {
75
+ releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
76
+ });
58
77
  }
59
78
  function createEvents(store) {
60
79
  const temp = new THREE.Vector3();
@@ -134,7 +153,7 @@ function createEvents(store) {
134
153
  while (eventObject) {
135
154
  var _r3f2;
136
155
 
137
- if ((_r3f2 = eventObject.__r3f) != null && _r3f2.handlers.count) intersections.push({ ...intersect,
156
+ if ((_r3f2 = eventObject.__r3f) != null && _r3f2.eventCount) intersections.push({ ...intersect,
138
157
  eventObject
139
158
  });
140
159
  eventObject = eventObject.parent;
@@ -153,7 +172,9 @@ function createEvents(store) {
153
172
  // intersect.
154
173
 
155
174
  if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
156
- intersections.push(...internal.capturedMap.get(event.pointerId).values());
175
+ for (let captureData of internal.capturedMap.get(event.pointerId).values()) {
176
+ intersections.push(captureData.intersection);
177
+ }
157
178
  }
158
179
 
159
180
  return intersections;
@@ -171,9 +192,6 @@ function createEvents(store) {
171
192
 
172
193
  if (intersections.length) {
173
194
  const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera);
174
-
175
- const releasePointerCapture = id => event.target.releasePointerCapture(id);
176
-
177
195
  const localState = {
178
196
  stopped: false
179
197
  };
@@ -186,23 +204,36 @@ function createEvents(store) {
186
204
  };
187
205
 
188
206
  const setPointerCapture = id => {
207
+ const captureData = {
208
+ intersection: hit,
209
+ target: event.target
210
+ };
211
+
189
212
  if (internal.capturedMap.has(id)) {
190
213
  // if the pointerId was previously captured, we add the hit to the
191
214
  // event capturedMap.
192
- internal.capturedMap.get(id).set(hit.eventObject, hit);
215
+ internal.capturedMap.get(id).set(hit.eventObject, captureData);
193
216
  } else {
194
217
  // if the pointerId was not previously captured, we create a map
195
218
  // containing the hitObject, and the hit. hitObject is used for
196
219
  // faster access.
197
- internal.capturedMap.set(id, new Map([[hit.eventObject, hit]]));
220
+ internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
198
221
  } // Call the original event now
199
222
  event.target.setPointerCapture(id);
223
+ };
224
+
225
+ const releasePointerCapture = id => {
226
+ const captures = internal.capturedMap.get(id);
227
+
228
+ if (captures) {
229
+ releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
230
+ }
200
231
  }; // Add native event props
201
232
 
202
233
 
203
- let extractEventProps = {};
234
+ let extractEventProps = {}; // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
204
235
 
205
- for (let prop in Object.getPrototypeOf(event)) {
236
+ for (let prop in event) {
206
237
  let property = event[prop]; // Only copy over atomics, leave functions alone as these should be
207
238
  // called as event.nativeEvent.fn()
208
239
 
@@ -271,13 +302,12 @@ function createEvents(store) {
271
302
  // When no objects were hit or the the hovered object wasn't found underneath the cursor
272
303
  // we call onPointerOut and delete the object from the hovered-elements map
273
304
  if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
274
- var _r3f3;
275
-
276
305
  const eventObject = hoveredObj.eventObject;
277
- const handlers = (_r3f3 = eventObject.__r3f) == null ? void 0 : _r3f3.handlers;
306
+ const instance = eventObject.__r3f;
307
+ const handlers = instance == null ? void 0 : instance.handlers;
278
308
  internal.hovered.delete(makeId(hoveredObj));
279
309
 
280
- if (handlers != null && handlers.count) {
310
+ if (instance != null && instance.eventCount) {
281
311
  // Clear out intersects, they are outdated by now
282
312
  const data = { ...hoveredObj,
283
313
  intersections: hits || []
@@ -299,9 +329,8 @@ function createEvents(store) {
299
329
  case 'onLostPointerCapture':
300
330
  return event => {
301
331
  if ('pointerId' in event) {
302
- // this will be a problem if one target releases the pointerId
303
- // and another one is still keeping it, as the line below
304
- // indifferently deletes all capturing references.
332
+ // If the object event interface had onLostPointerCapture, we'd call it here on every
333
+ // object that's getting removed.
305
334
  store.getState().internal.capturedMap.delete(event.pointerId);
306
335
  }
307
336
 
@@ -340,12 +369,11 @@ function createEvents(store) {
340
369
 
341
370
  if (isPointerMove) cancelPointer(hits);
342
371
  handleIntersects(hits, event, delta, data => {
343
- var _r3f4;
344
-
345
372
  const eventObject = data.eventObject;
346
- const handlers = (_r3f4 = eventObject.__r3f) == null ? void 0 : _r3f4.handlers; // Check presence of handlers
373
+ const instance = eventObject.__r3f;
374
+ const handlers = instance == null ? void 0 : instance.handlers; // Check presence of handlers
347
375
 
348
- if (!(handlers != null && handlers.count)) return;
376
+ if (!(instance != null && instance.eventCount)) return;
349
377
 
350
378
  if (isPointerMove) {
351
379
  // Move event ...
@@ -388,9 +416,9 @@ function createEvents(store) {
388
416
 
389
417
  function pointerMissed(event, objects) {
390
418
  objects.forEach(object => {
391
- var _r3f5;
419
+ var _r3f3;
392
420
 
393
- return (_r3f5 = object.__r3f) == null ? void 0 : _r3f5.handlers.onPointerMissed == null ? void 0 : _r3f5.handlers.onPointerMissed(event);
421
+ return (_r3f3 = object.__r3f) == null ? void 0 : _r3f3.handlers.onPointerMissed == null ? void 0 : _r3f3.handlers.onPointerMissed(event);
394
422
  });
395
423
  }
396
424
 
@@ -441,9 +469,8 @@ function prepare(object, state) {
441
469
  instance.__r3f = {
442
470
  root: null,
443
471
  memoizedProps: {},
444
- handlers: {
445
- count: 0
446
- },
472
+ eventCount: 0,
473
+ handlers: {},
447
474
  objects: [],
448
475
  parent: null,
449
476
  ...state
@@ -504,7 +531,7 @@ function createRenderer(roots) {
504
531
  }
505
532
 
506
533
  function applyProps(instance, data) {
507
- var _instance$__r3f3, _root$getState, _localState$handlers, _localState$handlers2, _instance$__r3f4;
534
+ var _instance$__r3f3, _root$getState, _instance$__r3f4;
508
535
 
509
536
  // Filter equals, events and reserved props
510
537
  const localState = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
@@ -514,7 +541,7 @@ function createRenderer(roots) {
514
541
  memoized,
515
542
  changes
516
543
  } = isDiffSet(data) ? data : diffProps(instance, data);
517
- const prevHandlers = (_localState$handlers = localState.handlers) == null ? void 0 : _localState$handlers.count; // Prepare memoized props
544
+ const prevHandlers = localState.eventCount; // Prepare memoized props
518
545
 
519
546
  if (instance.__r3f) instance.__r3f.memoizedProps = memoized;
520
547
  changes.forEach(([key, value, isEvent, keys]) => {
@@ -553,7 +580,7 @@ function createRenderer(roots) {
553
580
 
554
581
  if (isEvent) {
555
582
  if (value) localState.handlers[key] = value;else delete localState.handlers[key];
556
- localState.handlers.count = Object.keys(localState.handlers).length;
583
+ localState.eventCount = Object.keys(localState.handlers).length;
557
584
  } // Special treatment for objects with support for set/copy, and layers
558
585
  else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE.Layers)) {
559
586
  // If value is an array
@@ -561,21 +588,21 @@ function createRenderer(roots) {
561
588
  if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
562
589
  } // Test again target.copy(class) next ...
563
590
  else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) targetProp.copy(value); // If nothing else fits, just set the single value, ignore undefined
564
- // https://github.com/react-spring/react-three-fiber/issues/274
591
+ // https://github.com/pmndrs/react-three-fiber/issues/274
565
592
  else if (value !== undefined) {
566
593
  const isColor = targetProp instanceof THREE.Color; // Allow setting array scalars
567
594
 
568
595
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
569
596
  else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask; // Otherwise just set ...
570
597
  else targetProp.set(value); // Auto-convert sRGB colors, for now ...
571
- // https://github.com/react-spring/react-three-fiber/issues/344
598
+ // https://github.com/pmndrs/react-three-fiber/issues/344
572
599
 
573
600
  if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
574
601
  } // Else, just overwrite the value
575
602
 
576
603
  } else {
577
604
  currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
578
- // https://github.com/react-spring/react-three-fiber/issues/344
605
+ // https://github.com/pmndrs/react-three-fiber/issues/344
579
606
 
580
607
  if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) currentInstance[key].encoding = THREE.sRGBEncoding;
581
608
  }
@@ -583,12 +610,12 @@ function createRenderer(roots) {
583
610
  invalidateInstance(instance);
584
611
  });
585
612
 
586
- if (rootState.internal && instance.raycast && prevHandlers !== ((_localState$handlers2 = localState.handlers) == null ? void 0 : _localState$handlers2.count)) {
613
+ if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
587
614
  // Pre-emptively remove the instance from the interaction manager
588
615
  const index = rootState.internal.interaction.indexOf(instance);
589
616
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
590
617
 
591
- if (localState.handlers.count) rootState.internal.interaction.push(instance);
618
+ if (localState.eventCount) rootState.internal.interaction.push(instance);
592
619
  } // Call the update lifecycle when it is being updated
593
620
 
594
621
 
@@ -779,7 +806,7 @@ function createRenderer(roots) {
779
806
  } else if (is.fun(detachFn)) {
780
807
  detachFn(child, parentInstance);
781
808
  }
782
- } else if (child.isObject3D) {
809
+ } else if (child.isObject3D && parentInstance.isObject3D) {
783
810
  var _child$__r3f;
784
811
 
785
812
  parentInstance.remove(child); // Remove interactivity
@@ -1025,11 +1052,11 @@ const createStore = (applyProps, invalidate, advance, props) => {
1025
1052
  if (shadows) {
1026
1053
  gl.shadowMap.enabled = true;
1027
1054
  if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE.PCFSoftShadowMap;
1028
- } // Set color management
1055
+ } // Set color preferences
1029
1056
 
1030
1057
 
1031
- if (!linear) gl.outputEncoding = THREE.sRGBEncoding;
1032
- if (!flat) gl.toneMapping = THREE.ACESFilmicToneMapping; // clock.elapsedTime is updated using advance(timestamp)
1058
+ if (linear) gl.outputEncoding = THREE.LinearEncoding;
1059
+ if (flat) gl.toneMapping = THREE.NoToneMapping; // clock.elapsedTime is updated using advance(timestamp)
1033
1060
 
1034
1061
  if (frameloop === 'never') {
1035
1062
  clock.stop();
@@ -1218,38 +1245,45 @@ const createStore = (applyProps, invalidate, advance, props) => {
1218
1245
  }
1219
1246
  }
1220
1247
  };
1221
- }); // Resize camera and renderer on changes to size and pixelratio
1248
+ });
1249
+ const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1222
1250
 
1251
+ let oldSize = state.size;
1252
+ let oldDpr = state.viewport.dpr;
1223
1253
  rootState.subscribe(() => {
1224
1254
  const {
1225
1255
  camera,
1226
1256
  size,
1227
1257
  viewport,
1228
1258
  internal
1229
- } = rootState.getState(); // https://github.com/pmndrs/react-three-fiber/issues/92
1230
- // Do not mess with the camera if it belongs to the user
1231
-
1232
- if (!(internal.lastProps.camera instanceof THREE.Camera)) {
1233
- if (isOrthographicCamera(camera)) {
1234
- camera.left = size.width / -2;
1235
- camera.right = size.width / 2;
1236
- camera.top = size.height / 2;
1237
- camera.bottom = size.height / -2;
1238
- } else {
1239
- camera.aspect = size.width / size.height;
1240
- }
1259
+ } = rootState.getState();
1260
+
1261
+ if (size !== oldSize || viewport.dpr !== oldDpr) {
1262
+ // https://github.com/pmndrs/react-three-fiber/issues/92
1263
+ // Do not mess with the camera if it belongs to the user
1264
+ if (!(internal.lastProps.camera instanceof THREE.Camera)) {
1265
+ if (isOrthographicCamera(camera)) {
1266
+ camera.left = size.width / -2;
1267
+ camera.right = size.width / 2;
1268
+ camera.top = size.height / 2;
1269
+ camera.bottom = size.height / -2;
1270
+ } else {
1271
+ camera.aspect = size.width / size.height;
1272
+ }
1241
1273
 
1242
- camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
1243
- // Update matrix world since the renderer is a frame late
1274
+ camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
1275
+ // Update matrix world since the renderer is a frame late
1244
1276
 
1245
- camera.updateMatrixWorld();
1246
- } // Update renderer
1277
+ camera.updateMatrixWorld();
1278
+ } // Update renderer
1247
1279
 
1248
1280
 
1249
- gl.setPixelRatio(viewport.dpr);
1250
- gl.setSize(size.width, size.height);
1251
- }, state => [state.viewport.dpr, state.size], shallow);
1252
- const state = rootState.getState(); // Update size
1281
+ gl.setPixelRatio(viewport.dpr);
1282
+ gl.setSize(size.width, size.height);
1283
+ oldSize = size;
1284
+ oldDpr = viewport.dpr;
1285
+ }
1286
+ }); // Update size
1253
1287
 
1254
1288
  if (size) state.setSize(size.width, size.height); // Invalidate on any change
1255
1289
 
@@ -1613,7 +1647,11 @@ const createRendererInstance = (gl, canvas) => {
1613
1647
  antialias: true,
1614
1648
  alpha: true,
1615
1649
  ...gl
1616
- });
1650
+ }); // Set color management
1651
+
1652
+ renderer.outputEncoding = THREE.sRGBEncoding;
1653
+ renderer.toneMapping = THREE.ACESFilmicToneMapping; // Set gl props
1654
+
1617
1655
  if (gl) applyProps(renderer, gl);
1618
1656
  return renderer;
1619
1657
  };
@@ -0,0 +1 @@
1
+ export * from "../../dist/declarations/src/native";