@react-three/fiber 7.0.17 → 7.0.21

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();
@@ -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
 
@@ -298,9 +329,8 @@ function createEvents(store) {
298
329
  case 'onLostPointerCapture':
299
330
  return event => {
300
331
  if ('pointerId' in event) {
301
- // this will be a problem if one target releases the pointerId
302
- // and another one is still keeping it, as the line below
303
- // 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.
304
334
  store.getState().internal.capturedMap.delete(event.pointerId);
305
335
  }
306
336
 
@@ -314,7 +344,8 @@ function createEvents(store) {
314
344
  onPointerMissed,
315
345
  internal
316
346
  } = store.getState();
317
- prepareRay(event); // Get fresh intersects
347
+ prepareRay(event);
348
+ internal.lastEvent.current = event; // Get fresh intersects
318
349
 
319
350
  const isPointerMove = name === 'onPointerMove';
320
351
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
@@ -558,21 +589,21 @@ function createRenderer(roots) {
558
589
  if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
559
590
  } // Test again target.copy(class) next ...
560
591
  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
561
- // https://github.com/react-spring/react-three-fiber/issues/274
592
+ // https://github.com/pmndrs/react-three-fiber/issues/274
562
593
  else if (value !== undefined) {
563
594
  const isColor = targetProp instanceof THREE.Color; // Allow setting array scalars
564
595
 
565
596
  if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
566
597
  else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) targetProp.mask = value.mask; // Otherwise just set ...
567
598
  else targetProp.set(value); // Auto-convert sRGB colors, for now ...
568
- // https://github.com/react-spring/react-three-fiber/issues/344
599
+ // https://github.com/pmndrs/react-three-fiber/issues/344
569
600
 
570
601
  if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
571
602
  } // Else, just overwrite the value
572
603
 
573
604
  } else {
574
605
  currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
575
- // https://github.com/react-spring/react-three-fiber/issues/344
606
+ // https://github.com/pmndrs/react-three-fiber/issues/344
576
607
 
577
608
  if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) currentInstance[key].encoding = THREE.sRGBEncoding;
578
609
  }
@@ -776,7 +807,7 @@ function createRenderer(roots) {
776
807
  } else if (is.fun(detachFn)) {
777
808
  detachFn(child, parentInstance);
778
809
  }
779
- } else if (child.isObject3D) {
810
+ } else if (child.isObject3D && parentInstance.isObject3D) {
780
811
  var _child$__r3f;
781
812
 
782
813
  parentInstance.remove(child); // Remove interactivity
@@ -1022,11 +1053,11 @@ const createStore = (applyProps, invalidate, advance, props) => {
1022
1053
  if (shadows) {
1023
1054
  gl.shadowMap.enabled = true;
1024
1055
  if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE.PCFSoftShadowMap;
1025
- } // Set color management
1056
+ } // Set color preferences
1026
1057
 
1027
1058
 
1028
- if (!linear) gl.outputEncoding = THREE.sRGBEncoding;
1029
- if (!flat) gl.toneMapping = THREE.ACESFilmicToneMapping; // clock.elapsedTime is updated using advance(timestamp)
1059
+ if (linear) gl.outputEncoding = THREE.LinearEncoding;
1060
+ if (flat) gl.toneMapping = THREE.NoToneMapping; // clock.elapsedTime is updated using advance(timestamp)
1030
1061
 
1031
1062
  if (frameloop === 'never') {
1032
1063
  clock.stop();
@@ -1176,6 +1207,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1176
1207
  priority: 0,
1177
1208
  frames: 0,
1178
1209
  lastProps: props,
1210
+ lastEvent: /*#__PURE__*/React.createRef(null),
1179
1211
  interaction: [],
1180
1212
  hovered: new Map(),
1181
1213
  subscribers: [],
@@ -1215,38 +1247,45 @@ const createStore = (applyProps, invalidate, advance, props) => {
1215
1247
  }
1216
1248
  }
1217
1249
  };
1218
- }); // Resize camera and renderer on changes to size and pixelratio
1250
+ });
1251
+ const state = rootState.getState(); // Resize camera and renderer on changes to size and pixelratio
1219
1252
 
1253
+ let oldSize = state.size;
1254
+ let oldDpr = state.viewport.dpr;
1220
1255
  rootState.subscribe(() => {
1221
1256
  const {
1222
1257
  camera,
1223
1258
  size,
1224
1259
  viewport,
1225
1260
  internal
1226
- } = rootState.getState(); // https://github.com/pmndrs/react-three-fiber/issues/92
1227
- // Do not mess with the camera if it belongs to the user
1228
-
1229
- if (!(internal.lastProps.camera instanceof THREE.Camera)) {
1230
- if (isOrthographicCamera(camera)) {
1231
- camera.left = size.width / -2;
1232
- camera.right = size.width / 2;
1233
- camera.top = size.height / 2;
1234
- camera.bottom = size.height / -2;
1235
- } else {
1236
- camera.aspect = size.width / size.height;
1237
- }
1261
+ } = rootState.getState();
1262
+
1263
+ if (size !== oldSize || viewport.dpr !== oldDpr) {
1264
+ // https://github.com/pmndrs/react-three-fiber/issues/92
1265
+ // Do not mess with the camera if it belongs to the user
1266
+ if (!(internal.lastProps.camera instanceof THREE.Camera)) {
1267
+ if (isOrthographicCamera(camera)) {
1268
+ camera.left = size.width / -2;
1269
+ camera.right = size.width / 2;
1270
+ camera.top = size.height / 2;
1271
+ camera.bottom = size.height / -2;
1272
+ } else {
1273
+ camera.aspect = size.width / size.height;
1274
+ }
1238
1275
 
1239
- camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
1240
- // Update matrix world since the renderer is a frame late
1276
+ camera.updateProjectionMatrix(); // https://github.com/pmndrs/react-three-fiber/issues/178
1277
+ // Update matrix world since the renderer is a frame late
1241
1278
 
1242
- camera.updateMatrixWorld();
1243
- } // Update renderer
1279
+ camera.updateMatrixWorld();
1280
+ } // Update renderer
1244
1281
 
1245
1282
 
1246
- gl.setPixelRatio(viewport.dpr);
1247
- gl.setSize(size.width, size.height);
1248
- }, state => [state.viewport.dpr, state.size], shallow);
1249
- const state = rootState.getState(); // Update size
1283
+ gl.setPixelRatio(viewport.dpr);
1284
+ gl.setSize(size.width, size.height);
1285
+ oldSize = size;
1286
+ oldDpr = viewport.dpr;
1287
+ }
1288
+ }); // Update size
1250
1289
 
1251
1290
  if (size) state.setSize(size.width, size.height); // Invalidate on any change
1252
1291
 
@@ -1610,7 +1649,11 @@ const createRendererInstance = (gl, canvas) => {
1610
1649
  antialias: true,
1611
1650
  alpha: true,
1612
1651
  ...gl
1613
- });
1652
+ }); // Set color management
1653
+
1654
+ renderer.outputEncoding = THREE.sRGBEncoding;
1655
+ renderer.toneMapping = THREE.ACESFilmicToneMapping; // Set gl props
1656
+
1614
1657
  if (gl) applyProps(renderer, gl);
1615
1658
  return renderer;
1616
1659
  };
@@ -0,0 +1 @@
1
+ export * from "../../dist/declarations/src/native";