@react-three/fiber 8.0.0-beta-02 → 8.0.0-beta-03

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,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var THREE = require('three');
4
3
  var Reconciler = require('react-reconciler');
4
+ var scheduler = require('scheduler');
5
5
  var constants = require('react-reconciler/constants');
6
+ var THREE = require('three');
6
7
  var React = require('react');
7
8
  var suspendReact = require('suspend-react');
8
9
  var create = require('zustand');
@@ -18,17 +19,19 @@ function _interopNamespace(e) {
18
19
  var d = Object.getOwnPropertyDescriptor(e, k);
19
20
  Object.defineProperty(n, k, d.get ? d : {
20
21
  enumerable: true,
21
- get: function () { return e[k]; }
22
+ get: function () {
23
+ return e[k];
24
+ }
22
25
  });
23
26
  }
24
27
  });
25
28
  }
26
- n["default"] = e;
29
+ n['default'] = e;
27
30
  return Object.freeze(n);
28
31
  }
29
32
 
30
- var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
31
33
  var Reconciler__default = /*#__PURE__*/_interopDefault(Reconciler);
34
+ var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
32
35
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
33
36
  var create__default = /*#__PURE__*/_interopDefault(create);
34
37
 
@@ -40,7 +43,34 @@ const DEFAULT = '__default';
40
43
  const isDiffSet = def => def && !!def.memoized && !!def.changes;
41
44
  function calculateDpr(dpr) {
42
45
  return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr;
43
- } // A collection of compare functions
46
+ }
47
+ /**
48
+ * Picks or omits keys from an object
49
+ * `omit` will filter out keys, and otherwise cherry-pick them.
50
+ */
51
+
52
+ function filterKeys(obj, omit, ...keys) {
53
+ const keysToSelect = new Set(keys);
54
+ return Object.entries(obj).reduce((acc, [key, value]) => {
55
+ const shouldInclude = !omit;
56
+
57
+ if (keysToSelect.has(key) === shouldInclude) {
58
+ acc[key] = value;
59
+ }
60
+
61
+ return acc;
62
+ }, {});
63
+ }
64
+ /**
65
+ * Clones an object and cherry-picks keys.
66
+ */
67
+
68
+ const pick = (obj, keys) => filterKeys(obj, false, ...keys);
69
+ /**
70
+ * Clones an object and prunes or omits keys.
71
+ */
72
+
73
+ const omit = (obj, keys) => filterKeys(obj, true, ...keys); // A collection of compare functions
44
74
 
45
75
  const is = {
46
76
  obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
@@ -89,8 +119,7 @@ function dispose(obj) {
89
119
  if (obj.dispose && obj.type !== 'Scene') obj.dispose();
90
120
 
91
121
  for (const p in obj) {
92
- var _dispose, _ref;
93
- (_dispose = (_ref = p).dispose) == null ? void 0 : _dispose.call(_ref);
122
+ p.dispose == null ? void 0 : p.dispose();
94
123
  delete obj[p];
95
124
  }
96
125
  } // Each object in the scene carries a small LocalState descriptor
@@ -111,6 +140,49 @@ function prepare(object, state) {
111
140
  }
112
141
 
113
142
  return object;
143
+ }
144
+
145
+ function resolve(instance, key) {
146
+ let target = instance;
147
+
148
+ if (key.includes('-')) {
149
+ const entries = key.split('-');
150
+ const last = entries.pop();
151
+ target = entries.reduce((acc, key) => acc[key], instance);
152
+ return {
153
+ target,
154
+ key: last
155
+ };
156
+ } else return {
157
+ target,
158
+ key
159
+ };
160
+ }
161
+
162
+ function attach(parent, child, type) {
163
+ if (is.str(type)) {
164
+ const {
165
+ target,
166
+ key
167
+ } = resolve(parent, type);
168
+ parent.__r3f.previousAttach = target[key];
169
+ target[key] = child;
170
+ } else if (is.arr(type)) {
171
+ const [attach] = type;
172
+ if (is.str(attach)) parent[attach](child);else if (is.fun(attach)) attach(parent, child);
173
+ }
174
+ }
175
+ function detach(parent, child, type) {
176
+ if (is.str(type)) {
177
+ const {
178
+ target,
179
+ key
180
+ } = resolve(parent, type);
181
+ target[key] = parent.__r3f.previousAttach;
182
+ } else if (is.arr(type)) {
183
+ const [, detach] = type;
184
+ if (is.str(detach)) parent[detach](child);else if (is.fun(detach)) detach(parent, child);
185
+ }
114
186
  } // Shallow check arrays, but check objects atomically
115
187
 
116
188
  function checkShallow(a, b) {
@@ -140,7 +212,9 @@ function diffProps(instance, {
140
212
  if (remove) {
141
213
  const previousKeys = Object.keys(previous);
142
214
 
143
- for (let i = 0; i < previousKeys.length; i++) if (!props.hasOwnProperty(previousKeys[i])) entries.unshift([previousKeys[i], DEFAULT + 'remove']);
215
+ for (let i = 0; i < previousKeys.length; i++) {
216
+ if (!props.hasOwnProperty(previousKeys[i])) entries.unshift([previousKeys[i], DEFAULT + 'remove']);
217
+ }
144
218
  }
145
219
 
146
220
  entries.forEach(([key, value]) => {
@@ -211,7 +285,9 @@ function applyProps(instance, data) {
211
285
  value = defaultClassCall[targetProp]; // destory the instance
212
286
 
213
287
  if (defaultClassCall.dispose) defaultClassCall.dispose(); // instance does not have constructor, just set it to 0
214
- } else value = 0;
288
+ } else {
289
+ value = 0;
290
+ }
215
291
  } // Deal with pointer events ...
216
292
 
217
293
 
@@ -220,35 +296,39 @@ function applyProps(instance, data) {
220
296
  localState.eventCount = Object.keys(localState.handlers).length;
221
297
  } // Special treatment for objects with support for set/copy, and layers
222
298
  else if (targetProp && targetProp.set && (targetProp.copy || targetProp instanceof THREE__namespace.Layers)) {
223
- // If value is an array
224
- if (Array.isArray(value)) {
225
- if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
226
- } // Test again target.copy(class) next ...
227
- 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
228
- // https://github.com/react-spring/react-three-fiber/issues/274
229
- else if (value !== undefined) {
230
- const isColor = targetProp instanceof THREE__namespace.Color; // Allow setting array scalars
231
-
232
- if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
233
- else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
234
- else targetProp.set(value); // Auto-convert sRGB colors, for now ...
235
- // https://github.com/react-spring/react-three-fiber/issues/344
236
-
237
- if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
238
- } // Else, just overwrite the value
299
+ // If value is an array
300
+ if (Array.isArray(value)) {
301
+ if (targetProp.fromArray) targetProp.fromArray(value);else targetProp.set(...value);
302
+ } // Test again target.copy(class) next ...
303
+ else if (targetProp.copy && value && value.constructor && targetProp.constructor.name === value.constructor.name) {
304
+ targetProp.copy(value);
305
+ } // If nothing else fits, just set the single value, ignore undefined
306
+ // https://github.com/pmndrs/react-three-fiber/issues/274
307
+ else if (value !== undefined) {
308
+ const isColor = targetProp instanceof THREE__namespace.Color; // Allow setting array scalars
309
+
310
+ if (!isColor && targetProp.setScalar) targetProp.setScalar(value); // Layers have no copy function, we must therefore copy the mask property
311
+ else if (targetProp instanceof THREE__namespace.Layers && value instanceof THREE__namespace.Layers) targetProp.mask = value.mask; // Otherwise just set ...
312
+ else targetProp.set(value); // Auto-convert sRGB colors, for now ...
313
+ // https://github.com/pmndrs/react-three-fiber/issues/344
314
+
315
+ if (!rootState.linear && isColor) targetProp.convertSRGBToLinear();
316
+ } // Else, just overwrite the value
239
317
 
240
- } else {
241
- currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
242
- // https://github.com/react-spring/react-three-fiber/issues/344
318
+ } else {
319
+ currentInstance[key] = value; // Auto-convert sRGB textures, for now ...
320
+ // https://github.com/pmndrs/react-three-fiber/issues/344
243
321
 
244
- if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
245
- }
322
+ if (!rootState.linear && currentInstance[key] instanceof THREE__namespace.Texture) {
323
+ currentInstance[key].encoding = THREE__namespace.sRGBEncoding;
324
+ }
325
+ }
246
326
 
247
327
  invalidateInstance(instance);
248
328
  return instance;
249
329
  });
250
330
 
251
- if (rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
331
+ if (localState.parent && rootState.internal && instance.raycast && prevHandlers !== localState.eventCount) {
252
332
  // Pre-emptively remove the instance from the interaction manager
253
333
  const index = rootState.internal.interaction.indexOf(instance);
254
334
  if (index > -1) rootState.internal.interaction.splice(index, 1); // Add the instance to the interaction manager only when it has handlers
@@ -272,7 +352,8 @@ function updateInstance(instance) {
272
352
  function makeId(event) {
273
353
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
274
354
  }
275
- /** Release pointer captures.
355
+ /**
356
+ * Release pointer captures.
276
357
  * This is called by releasePointerCapture in the API, and when an object is removed.
277
358
  */
278
359
 
@@ -559,13 +640,16 @@ function createEvents(store) {
559
640
 
560
641
  case 'onLostPointerCapture':
561
642
  return event => {
562
- if ('pointerId' in event) {
643
+ const {
644
+ internal
645
+ } = store.getState();
646
+
647
+ if ('pointerId' in event && !internal.capturedMap.has(event.pointerId)) {
563
648
  // If the object event interface had onLostPointerCapture, we'd call it here on every
564
649
  // object that's getting removed.
565
- store.getState().internal.capturedMap.delete(event.pointerId);
650
+ internal.capturedMap.delete(event.pointerId);
651
+ cancelPointer([]);
566
652
  }
567
-
568
- cancelPointer([]);
569
653
  };
570
654
  } // Any other pointer goes here ...
571
655
 
@@ -575,7 +659,8 @@ function createEvents(store) {
575
659
  onPointerMissed,
576
660
  internal
577
661
  } = store.getState();
578
- prepareRay(event); // Get fresh intersects
662
+ prepareRay(event);
663
+ internal.lastEvent.current = event; // Get fresh intersects
579
664
 
580
665
  const isPointerMove = name === 'onPointerMove';
581
666
  const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick';
@@ -633,12 +718,17 @@ function createEvents(store) {
633
718
  if (handler) {
634
719
  // Forward all events back to their respective handlers with the exception of click events,
635
720
  // which must use the initial target
636
- if (name !== 'onClick' && name !== 'onContextMenu' && name !== 'onDoubleClick' || internal.initialHits.includes(eventObject)) {
721
+ if (!isClickEvent || internal.initialHits.includes(eventObject)) {
637
722
  // Missed events have to come first
638
723
  pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object))); // Now call the handler
639
724
 
640
725
  handler(data);
641
726
  }
727
+ } else {
728
+ // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
729
+ if (isClickEvent && internal.initialHits.includes(eventObject)) {
730
+ pointerMissed(event, internal.interaction.filter(object => !internal.initialHits.includes(object)));
731
+ }
642
732
  }
643
733
  }
644
734
  });
@@ -684,6 +774,7 @@ let extend = objects => void (catalogue = { ...catalogue,
684
774
  function createRenderer(roots, getEventPriority) {
685
775
  function createInstance(type, {
686
776
  args = [],
777
+ attach,
687
778
  ...props
688
779
  }, root, hostContext, internalInstanceHandle) {
689
780
  let name = `${type[0].toUpperCase()}${type.slice(1)}`;
@@ -700,41 +791,39 @@ function createRenderer(roots, getEventPriority) {
700
791
  } // Assert that by now we have a valid root
701
792
 
702
793
 
703
- if (!root || !isStore(root)) throw `No valid root for ${name}!`;
794
+ if (!root || !isStore(root)) throw `No valid root for ${name}!`; // Auto-attach geometries and materials
795
+
796
+ if (attach === undefined) {
797
+ if (name.endsWith('Geometry')) attach = 'geometry';else if (name.endsWith('Material')) attach = 'material';
798
+ }
704
799
 
705
800
  if (type === 'primitive') {
706
801
  if (props.object === undefined) throw `Primitives without 'object' are invalid!`;
707
802
  const object = props.object;
708
803
  instance = prepare(object, {
709
804
  root,
805
+ attach,
710
806
  primitive: true
711
807
  });
712
808
  } else {
713
- const target = catalogue[name] || THREE__namespace[name];
714
- if (!target) throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; // Instanciate new object, link it to the root
809
+ const target = catalogue[name];
810
+
811
+ if (!target) {
812
+ throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`;
813
+ } // Throw if an object or literal was passed for args
814
+
815
+
816
+ if (!Array.isArray(args)) throw 'The args prop must be an array!'; // Instanciate new object, link it to the root
715
817
  // Append memoized props with args so it's not forgotten
716
818
 
717
819
  instance = prepare(new target(...args), {
718
820
  root,
821
+ attach,
822
+ // TODO: Figure out what this is for
719
823
  memoizedProps: {
720
824
  args: args.length === 0 ? null : args
721
825
  }
722
826
  });
723
- } // Auto-attach geometries and materials
724
-
725
-
726
- if (!('attachFns' in props)) {
727
- if (name.endsWith('Geometry')) {
728
- props = {
729
- attach: 'geometry',
730
- ...props
731
- };
732
- } else if (name.endsWith('Material')) {
733
- props = {
734
- attach: 'material',
735
- ...props
736
- };
737
- }
738
827
  } // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
739
828
  // view yet. If the callback relies on references for instance, they won't be ready yet, this is
740
829
  // why it passes "true" here
@@ -745,42 +834,22 @@ function createRenderer(roots, getEventPriority) {
745
834
  }
746
835
 
747
836
  function appendChild(parentInstance, child) {
748
- let addedAsChild = false;
837
+ let added = false;
749
838
 
750
839
  if (child) {
751
840
  // The attach attribute implies that the object attaches itself on the parent
752
- if (child.attachArray) {
753
- if (!is.arr(parentInstance[child.attachArray])) parentInstance[child.attachArray] = [];
754
- parentInstance[child.attachArray].push(child);
755
- } else if (child.attachObject) {
756
- if (!is.obj(parentInstance[child.attachObject[0]])) parentInstance[child.attachObject[0]] = {};
757
- parentInstance[child.attachObject[0]][child.attachObject[1]] = child;
758
- } else if (child.attach && !is.fun(child.attach)) {
759
- parentInstance[child.attach] = child;
760
- } else if (is.arr(child.attachFns)) {
761
- const [attachFn] = child.attachFns;
762
-
763
- if (is.str(attachFn) && is.fun(parentInstance[attachFn])) {
764
- parentInstance[attachFn](child);
765
- } else if (is.fun(attachFn)) {
766
- attachFn(child, parentInstance);
767
- }
841
+ if (child.__r3f.attach) {
842
+ attach(parentInstance, child, child.__r3f.attach);
768
843
  } else if (child.isObject3D && parentInstance.isObject3D) {
769
844
  // add in the usual parent-child way
770
845
  parentInstance.add(child);
771
- addedAsChild = true;
772
- }
773
-
774
- if (!addedAsChild) {
775
- // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
776
- // that is, anything that's a child in React but not a child in the scenegraph.
777
- parentInstance.__r3f.objects.push(child);
778
- }
846
+ added = true;
847
+ } // This is for anything that used attach, and for non-Object3Ds that don't get attached to props;
848
+ // that is, anything that's a child in React but not a child in the scenegraph.
779
849
 
780
- if (!child.__r3f) {
781
- prepare(child, {});
782
- }
783
850
 
851
+ if (!added) parentInstance.__r3f.objects.push(child);
852
+ if (!child.__r3f) prepare(child, {});
784
853
  child.__r3f.parent = parentInstance;
785
854
  updateInstance(child);
786
855
  invalidateInstance(child);
@@ -791,13 +860,8 @@ function createRenderer(roots, getEventPriority) {
791
860
  let added = false;
792
861
 
793
862
  if (child) {
794
- if (child.attachArray) {
795
- const array = parentInstance[child.attachArray];
796
- if (!is.arr(array)) parentInstance[child.attachArray] = [];
797
- array.splice(array.indexOf(beforeChild), 0, child);
798
- } else if (child.attachObject || child.attach && !is.fun(child.attach)) {
799
- // attach and attachObject don't have an order anyway, so just append
800
- return appendChild(parentInstance, child);
863
+ if (child.__r3f.attach) {
864
+ attach(parentInstance, child, child.__r3f.attach);
801
865
  } else if (child.isObject3D && parentInstance.isObject3D) {
802
866
  child.parent = parentInstance;
803
867
  child.dispatchEvent({
@@ -809,14 +873,8 @@ function createRenderer(roots, getEventPriority) {
809
873
  added = true;
810
874
  }
811
875
 
812
- if (!added) {
813
- parentInstance.__r3f.objects.push(child);
814
- }
815
-
816
- if (!child.__r3f) {
817
- prepare(child, {});
818
- }
819
-
876
+ if (!added) parentInstance.__r3f.objects.push(child);
877
+ if (!child.__r3f) prepare(child, {});
820
878
  child.__r3f.parent = parentInstance;
821
879
  updateInstance(child);
822
880
  invalidateInstance(child);
@@ -831,29 +889,13 @@ function createRenderer(roots, getEventPriority) {
831
889
  if (child) {
832
890
  var _parentInstance$__r3f, _child$__r3f2;
833
891
 
834
- if (child.__r3f) {
835
- child.__r3f.parent = null;
836
- }
837
-
838
- if ((_parentInstance$__r3f = parentInstance.__r3f) != null && _parentInstance$__r3f.objects) {
839
- parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child);
840
- } // Remove attachment
892
+ // Clear the parent reference
893
+ if (child.__r3f) child.__r3f.parent = null; // Remove child from the parents objects
841
894
 
895
+ if ((_parentInstance$__r3f = parentInstance.__r3f) != null && _parentInstance$__r3f.objects) parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child); // Remove attachment
842
896
 
843
- if (child.attachArray) {
844
- parentInstance[child.attachArray] = parentInstance[child.attachArray].filter(x => x !== child);
845
- } else if (child.attachObject) {
846
- delete parentInstance[child.attachObject[0]][child.attachObject[1]];
847
- } else if (child.attach && !is.fun(child.attach)) {
848
- parentInstance[child.attach] = null;
849
- } else if (is.arr(child.attachFns)) {
850
- const [, detachFn] = child.attachFns;
851
-
852
- if (is.str(detachFn) && is.fun(parentInstance[detachFn])) {
853
- parentInstance[detachFn](child);
854
- } else if (is.fun(detachFn)) {
855
- detachFn(child, parentInstance);
856
- }
897
+ if (child.__r3f.attach) {
898
+ detach(parentInstance, child, child.__r3f.attach);
857
899
  } else if (child.isObject3D && parentInstance.isObject3D) {
858
900
  var _child$__r3f;
859
901
 
@@ -895,7 +937,7 @@ function createRenderer(roots, getEventPriority) {
895
937
 
896
938
 
897
939
  if (shouldDispose && child.dispose && child.type !== 'Scene') {
898
- reconciler.runWithPriority(constants.IdleEventPriority, () => {
940
+ scheduler.unstable_scheduleCallback(scheduler.unstable_IdlePriority, () => {
899
941
  try {
900
942
  child.dispose();
901
943
  } catch (e) {
@@ -942,7 +984,7 @@ function createRenderer(roots, getEventPriority) {
942
984
  });
943
985
  }
944
986
 
945
- const reconciler = Reconciler__default["default"]({
987
+ const reconciler = Reconciler__default['default']({
946
988
  appendChildToContainer: (parentInstance, child) => {
947
989
  const {
948
990
  container,
@@ -956,7 +998,9 @@ function createRenderer(roots, getEventPriority) {
956
998
  insertInContainerBefore: (parentInstance, child, beforeChild) => insertBefore(getContainer(parentInstance, child).container, child, beforeChild),
957
999
 
958
1000
  prepareUpdate(instance, type, oldProps, newProps) {
959
- if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) return [true];else {
1001
+ if (instance.__r3f.primitive && newProps.object && newProps.object !== instance) {
1002
+ return [true];
1003
+ } else {
960
1004
  // This is a data object, let's extract critical information about it
961
1005
  const {
962
1006
  args: argsNew = [],
@@ -967,7 +1011,9 @@ function createRenderer(roots, getEventPriority) {
967
1011
  args: argsOld = [],
968
1012
  children: cO,
969
1013
  ...restOld
970
- } = oldProps; // If it has new props or arguments, then it needs to be re-instanciated
1014
+ } = oldProps; // Throw if an object or literal was passed for args
1015
+
1016
+ if (!Array.isArray(argsNew)) throw 'The args prop must be an array!'; // If it has new props or arguments, then it needs to be re-instanciated
971
1017
 
972
1018
  if (argsNew.some((value, index) => value !== argsOld[index])) return [true]; // Create a diff-set, flag if there are any changes
973
1019
 
@@ -985,17 +1031,29 @@ function createRenderer(roots, getEventPriority) {
985
1031
  },
986
1032
 
987
1033
  hideInstance(instance) {
988
- if (instance.isObject3D) {
989
- instance.visible = false;
990
- invalidateInstance(instance);
991
- }
1034
+ var _instance$__r3f2;
1035
+
1036
+ // Deatch while the instance is hidden
1037
+ const {
1038
+ attach: type,
1039
+ parent
1040
+ } = (_instance$__r3f2 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f2 : {};
1041
+ if (type && parent) detach(parent, instance, type);
1042
+ if (instance.isObject3D) instance.visible = false;
1043
+ invalidateInstance(instance);
992
1044
  },
993
1045
 
994
1046
  unhideInstance(instance, props) {
995
- if (instance.isObject3D && props.visible == null || props.visible) {
996
- instance.visible = true;
997
- invalidateInstance(instance);
998
- }
1047
+ var _instance$__r3f3;
1048
+
1049
+ // Re-attach when the instance is unhidden
1050
+ const {
1051
+ attach: type,
1052
+ parent
1053
+ } = (_instance$__r3f3 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f3 : {};
1054
+ if (type && parent) attach(parent, instance, type);
1055
+ if (instance.isObject3D && props.visible == null || props.visible) instance.visible = true;
1056
+ invalidateInstance(instance);
999
1057
  },
1000
1058
 
1001
1059
  createInstance,
@@ -1024,8 +1082,30 @@ function createRenderer(roots, getEventPriority) {
1024
1082
  getRootHostContext: () => null,
1025
1083
  getChildHostContext: parentHostContext => parentHostContext,
1026
1084
  createTextInstance: () => {},
1027
- finalizeInitialChildren: () => false,
1028
- commitMount: () => {},
1085
+
1086
+ finalizeInitialChildren(instance) {
1087
+ var _instance$__r3f4;
1088
+
1089
+ // https://github.com/facebook/react/issues/20271
1090
+ // Returning true will trigger commitMount
1091
+ const localState = (_instance$__r3f4 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f4 : {};
1092
+ return !!localState.handlers;
1093
+ },
1094
+
1095
+ commitMount(instance)
1096
+ /*, type, props*/
1097
+ {
1098
+ var _instance$__r3f5;
1099
+
1100
+ // https://github.com/facebook/react/issues/20271
1101
+ // This will make sure events are only added once to the central container
1102
+ const localState = (_instance$__r3f5 = instance == null ? void 0 : instance.__r3f) != null ? _instance$__r3f5 : {};
1103
+
1104
+ if (instance.raycast && localState.handlers && localState.eventCount) {
1105
+ instance.__r3f.root.getState().internal.interaction.push(instance);
1106
+ }
1107
+ },
1108
+
1029
1109
  shouldDeprioritizeSubtree: () => false,
1030
1110
  prepareForCommit: () => null,
1031
1111
  preparePortalMount: containerInfo => prepare(containerInfo),
@@ -1075,7 +1155,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1075
1155
  clock.elapsedTime = 0;
1076
1156
  }
1077
1157
 
1078
- const rootState = create__default["default"]((set, get) => {
1158
+ const rootState = create__default['default']((set, get) => {
1079
1159
  // Create custom raycaster
1080
1160
  const raycaster = new THREE__namespace.Raycaster();
1081
1161
  const {
@@ -1239,6 +1319,9 @@ const createStore = (applyProps, invalidate, advance, props) => {
1239
1319
  dpr: calculateDpr(dpr)
1240
1320
  }
1241
1321
  })),
1322
+ setFrameloop: (frameloop = 'always') => set(() => ({
1323
+ frameloop
1324
+ })),
1242
1325
  events: {
1243
1326
  connected: false
1244
1327
  },
@@ -1247,6 +1330,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1247
1330
  priority: 0,
1248
1331
  frames: 0,
1249
1332
  lastProps: props,
1333
+ lastEvent: /*#__PURE__*/React__namespace.createRef(),
1250
1334
  interaction: [],
1251
1335
  hovered: new Map(),
1252
1336
  subscribers: [],
@@ -1303,7 +1387,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1303
1387
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1304
1388
  // https://github.com/pmndrs/react-three-fiber/issues/92
1305
1389
  // Do not mess with the camera if it belongs to the user
1306
- if (!(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1390
+ if (!camera.manual && !(internal.lastProps.camera instanceof THREE__namespace.Camera)) {
1307
1391
  if (isOrthographicCamera(camera)) {
1308
1392
  camera.left = size.width / -2;
1309
1393
  camera.right = size.width / 2;
@@ -1387,7 +1471,9 @@ function createLoop(roots) {
1387
1471
 
1388
1472
  const state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1389
1473
 
1390
- if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) repeat += render(timestamp, state);
1474
+ if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
1475
+ repeat += render(timestamp, state);
1476
+ }
1391
1477
  }); // Run after-effects
1392
1478
 
1393
1479
  run(globalAfterEffects, timestamp); // Keep on looping if anything invalidates the frameloop
@@ -1493,6 +1579,8 @@ exports.dispose = dispose;
1493
1579
  exports.extend = extend;
1494
1580
  exports.is = is;
1495
1581
  exports.isRenderer = isRenderer;
1582
+ exports.omit = omit;
1583
+ exports.pick = pick;
1496
1584
  exports.threeTypes = threeTypes;
1497
1585
  exports.useFrame = useFrame;
1498
1586
  exports.useGraph = useGraph;