@react-three/fiber 7.0.3 → 7.0.7
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/CHANGELOG.md +25 -0
- package/dist/declarations/src/core/hooks.d.ts +2 -0
- package/dist/declarations/src/core/is.d.ts +3 -3
- package/dist/declarations/src/core/renderer.d.ts +3 -0
- package/dist/declarations/src/core/store.d.ts +1 -0
- package/dist/declarations/src/three-types.d.ts +2 -0
- package/dist/declarations/src/web/index.d.ts +1 -1
- package/dist/react-three-fiber.cjs.dev.js +56 -27
- package/dist/react-three-fiber.cjs.prod.js +56 -27
- package/dist/react-three-fiber.esm.js +56 -28
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
# @react-three/fiber
|
|
2
2
|
|
|
3
|
+
## 7.0.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0375896: Simplify useframe, support instanced event cancelation, silence disposal
|
|
8
|
+
|
|
9
|
+
## 7.0.6
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- fb052ad: Fix babel-env browserslist transpiling into old code"
|
|
14
|
+
|
|
15
|
+
## 7.0.5
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- c97794a: Add useLoader.clear(Loader, input)
|
|
20
|
+
|
|
21
|
+
## 7.0.4
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 974ecfb: Allow elements to define attachFns for specific mount/unmount
|
|
26
|
+
|
|
3
27
|
## 7.0.2
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
6
30
|
|
|
31
|
+
- a97aca3: Add controls state field
|
|
7
32
|
- 4c703d6: fix rttr didn't work with r130
|
|
8
33
|
|
|
9
34
|
## 7.0.0
|
|
@@ -17,11 +17,13 @@ export declare type ObjectMap = {
|
|
|
17
17
|
[name: string]: THREE.Material;
|
|
18
18
|
};
|
|
19
19
|
};
|
|
20
|
+
export declare function useStore(): import("zustand").UseStore<RootState>;
|
|
20
21
|
export declare function useThree<T = RootState>(selector?: StateSelector<RootState, T>, equalityFn?: EqualityChecker<T>): T;
|
|
21
22
|
export declare function useFrame(callback: RenderCallback, renderPriority?: number): null;
|
|
22
23
|
export declare function useGraph(object: THREE.Object3D): ObjectMap;
|
|
23
24
|
export declare function useLoader<T, U extends string | string[]>(Proto: new () => LoaderResult<T>, input: U, extensions?: Extensions, onProgress?: (event: ProgressEvent<EventTarget>) => void): U extends any[] ? BranchingReturn<T, GLTF, GLTF & ObjectMap>[] : BranchingReturn<T, GLTF, GLTF & ObjectMap>;
|
|
24
25
|
export declare namespace useLoader {
|
|
25
26
|
var preload: <T, U extends string | string[]>(Proto: new () => LoaderResult<T>, input: U, extensions?: Extensions | undefined) => undefined;
|
|
27
|
+
var clear: <T, U extends string | string[]>(Proto: new () => LoaderResult<T>, input: U) => void;
|
|
26
28
|
}
|
|
27
29
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export declare const is: {
|
|
2
2
|
obj: (a: any) => boolean;
|
|
3
|
-
fun: (a: any) =>
|
|
4
|
-
str: (a: any) =>
|
|
5
|
-
num: (a: any) =>
|
|
3
|
+
fun: (a: any) => a is Function;
|
|
4
|
+
str: (a: any) => a is string;
|
|
5
|
+
num: (a: any) => a is number;
|
|
6
6
|
und: (a: any) => boolean;
|
|
7
7
|
arr: (a: any) => boolean;
|
|
8
8
|
equ(a: any, b: any): boolean;
|
|
@@ -19,11 +19,14 @@ export declare type LocalState = {
|
|
|
19
19
|
export declare type ClassConstructor = {
|
|
20
20
|
new (): void;
|
|
21
21
|
};
|
|
22
|
+
export declare type AttachFnType = (self: Instance, parent: Instance) => void;
|
|
23
|
+
export declare type AttachFnsType = [attach: string | AttachFnType, detach: string | AttachFnType];
|
|
22
24
|
export declare type BaseInstance = Omit<THREE.Object3D, 'parent' | 'children' | 'attach' | 'add' | 'remove' | 'raycast'> & {
|
|
23
25
|
__r3f: LocalState;
|
|
24
26
|
parent: Instance | null;
|
|
25
27
|
children: Instance[];
|
|
26
28
|
attach?: string;
|
|
29
|
+
attachFns?: AttachFnsType;
|
|
27
30
|
remove: (...object: Instance[]) => Instance;
|
|
28
31
|
add: (...object: Instance[]) => Instance;
|
|
29
32
|
raycast?: (raycaster: THREE.Raycaster, intersects: THREE.Intersection[]) => void;
|
|
@@ -14,10 +14,12 @@ export declare type Color = ConstructorParameters<typeof THREE.Color> | THREE.Co
|
|
|
14
14
|
export declare type ColorArray = typeof THREE.Color | Parameters<THREE.Color['set']>;
|
|
15
15
|
export declare type Layers = THREE.Layers | Parameters<THREE.Layers['set']>[0];
|
|
16
16
|
export declare type Quaternion = THREE.Quaternion | Parameters<THREE.Quaternion['set']>;
|
|
17
|
+
export declare type AttachCallback = string | ((child: any, parentInstance: any) => void);
|
|
17
18
|
export interface NodeProps<T, P> {
|
|
18
19
|
attach?: string;
|
|
19
20
|
attachArray?: string;
|
|
20
21
|
attachObject?: [target: string, name: string];
|
|
22
|
+
attachFns?: [AttachCallback, AttachCallback];
|
|
21
23
|
args?: Args<P>;
|
|
22
24
|
children?: React.ReactNode;
|
|
23
25
|
ref?: React.Ref<React.ReactNode>;
|
|
@@ -13,7 +13,7 @@ declare const modes: readonly ["legacy", "blocking", "concurrent"];
|
|
|
13
13
|
declare const invalidate: (state?: RootState | undefined) => void, advance: (timestamp: number, runGlobalEffects?: boolean, state?: RootState | undefined) => void;
|
|
14
14
|
declare const reconciler: import("react-reconciler").Reconciler<unknown, unknown, unknown, unknown, unknown>, applyProps: (instance: import("../core/renderer").Instance, newProps: import("../core/renderer").InstanceProps, oldProps?: import("../core/renderer").InstanceProps, accumulative?: boolean) => void;
|
|
15
15
|
export declare type RenderProps<TCanvas extends Element> = Omit<StoreProps, 'gl' | 'events' | 'size'> & {
|
|
16
|
-
gl?: THREE.WebGLRenderer | THREE.WebGLRendererParameters
|
|
16
|
+
gl?: THREE.WebGLRenderer | Partial<THREE.WebGLRendererParameters>;
|
|
17
17
|
events?: (store: UseStore<RootState>) => EventManager<TCanvas>;
|
|
18
18
|
size?: Size;
|
|
19
19
|
mode?: typeof modes[number];
|
|
@@ -74,7 +74,7 @@ const is = {
|
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
function makeId(event) {
|
|
77
|
-
return (event.eventObject || event.object).uuid + '/' + event.index;
|
|
77
|
+
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
function removeInteractivity(store, object) {
|
|
@@ -306,7 +306,7 @@ function createEvents(store) {
|
|
|
306
306
|
Array.from(internal.hovered.values()).forEach(hoveredObj => {
|
|
307
307
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
308
308
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
309
|
-
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index)) {
|
|
309
|
+
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
310
310
|
const eventObject = hoveredObj.eventObject;
|
|
311
311
|
const handlers = eventObject.__r3f.handlers;
|
|
312
312
|
internal.hovered.delete(makeId(hoveredObj));
|
|
@@ -704,16 +704,18 @@ function createRenderer(roots) {
|
|
|
704
704
|
} // Auto-attach geometries and materials
|
|
705
705
|
|
|
706
706
|
|
|
707
|
-
if (
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
707
|
+
if (!('attachFns' in props)) {
|
|
708
|
+
if (name.endsWith('Geometry')) {
|
|
709
|
+
props = {
|
|
710
|
+
attach: 'geometry',
|
|
711
|
+
...props
|
|
712
|
+
};
|
|
713
|
+
} else if (name.endsWith('Material')) {
|
|
714
|
+
props = {
|
|
715
|
+
attach: 'material',
|
|
716
|
+
...props
|
|
717
|
+
};
|
|
718
|
+
}
|
|
717
719
|
} // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
|
|
718
720
|
// view yet. If the callback relies on references for instance, they won't be ready yet, this is
|
|
719
721
|
// why it passes "true" here
|
|
@@ -736,6 +738,14 @@ function createRenderer(roots) {
|
|
|
736
738
|
parentInstance[child.attachObject[0]][child.attachObject[1]] = child;
|
|
737
739
|
} else if (child.attach && !is.fun(child.attach)) {
|
|
738
740
|
parentInstance[child.attach] = child;
|
|
741
|
+
} else if (is.arr(child.attachFns)) {
|
|
742
|
+
const [attachFn] = child.attachFns;
|
|
743
|
+
|
|
744
|
+
if (is.str(attachFn) && is.fun(parentInstance[attachFn])) {
|
|
745
|
+
parentInstance[attachFn](child);
|
|
746
|
+
} else if (is.fun(attachFn)) {
|
|
747
|
+
attachFn(child, parentInstance);
|
|
748
|
+
}
|
|
739
749
|
} else if (child.isObject3D) {
|
|
740
750
|
// add in the usual parent-child way
|
|
741
751
|
parentInstance.add(child);
|
|
@@ -814,6 +824,14 @@ function createRenderer(roots) {
|
|
|
814
824
|
delete parentInstance[child.attachObject[0]][child.attachObject[1]];
|
|
815
825
|
} else if (child.attach && !is.fun(child.attach)) {
|
|
816
826
|
parentInstance[child.attach] = null;
|
|
827
|
+
} else if (is.arr(child.attachFns)) {
|
|
828
|
+
const [, detachFn] = child.attachFns;
|
|
829
|
+
|
|
830
|
+
if (is.str(detachFn) && is.fun(parentInstance[detachFn])) {
|
|
831
|
+
parentInstance[detachFn](child);
|
|
832
|
+
} else if (is.fun(detachFn)) {
|
|
833
|
+
detachFn(child, parentInstance);
|
|
834
|
+
}
|
|
817
835
|
} else if (child.isObject3D) {
|
|
818
836
|
var _child$__r3f;
|
|
819
837
|
|
|
@@ -826,7 +844,7 @@ function createRenderer(roots) {
|
|
|
826
844
|
// Never dispose of primitives because their state may be kept outside of React!
|
|
827
845
|
// In order for an object to be able to dispose it has to have
|
|
828
846
|
// - a dispose method,
|
|
829
|
-
// - it cannot be
|
|
847
|
+
// - it cannot be a <primitive object={...} />
|
|
830
848
|
// - it cannot be a THREE.Scene, because three has broken it's own api
|
|
831
849
|
//
|
|
832
850
|
// Since disposal is recursive, we can check the optional dispose arg, which will be undefined
|
|
@@ -855,7 +873,13 @@ function createRenderer(roots) {
|
|
|
855
873
|
|
|
856
874
|
|
|
857
875
|
if (shouldDispose && child.dispose && child.type !== 'Scene') {
|
|
858
|
-
scheduler.unstable_runWithPriority(scheduler.unstable_IdlePriority, () =>
|
|
876
|
+
scheduler.unstable_runWithPriority(scheduler.unstable_IdlePriority, () => {
|
|
877
|
+
try {
|
|
878
|
+
child.dispose();
|
|
879
|
+
} catch (e) {
|
|
880
|
+
/* ... */
|
|
881
|
+
}
|
|
882
|
+
});
|
|
859
883
|
}
|
|
860
884
|
|
|
861
885
|
invalidateInstance(parentInstance);
|
|
@@ -1163,6 +1187,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1163
1187
|
flat,
|
|
1164
1188
|
scene: prepare(new THREE__namespace.Scene()),
|
|
1165
1189
|
camera,
|
|
1190
|
+
controls: null,
|
|
1166
1191
|
raycaster,
|
|
1167
1192
|
clock,
|
|
1168
1193
|
mouse: new THREE__namespace.Vector2(),
|
|
@@ -1237,8 +1262,8 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1237
1262
|
internal: { ...internal,
|
|
1238
1263
|
// If this subscription was given a priority, it takes rendering into its own hands
|
|
1239
1264
|
// For that reason we switch off automatic rendering and increase the manual flag
|
|
1240
|
-
// As long as this flag is positive
|
|
1241
|
-
//
|
|
1265
|
+
// As long as this flag is positive there can be no internal rendering at all
|
|
1266
|
+
// because there could be multiple render subscriptions
|
|
1242
1267
|
priority: internal.priority + (priority > 0 ? 1 : 0),
|
|
1243
1268
|
// Register subscriber and sort layers from lowest to highest, meaning,
|
|
1244
1269
|
// highest priority renders last (on top of the other frames)
|
|
@@ -1558,23 +1583,21 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1558
1583
|
}, fallback));
|
|
1559
1584
|
});
|
|
1560
1585
|
|
|
1586
|
+
function useStore() {
|
|
1587
|
+
const store = React__namespace.useContext(context);
|
|
1588
|
+
if (!store) throw `R3F hooks can only be used within the Canvas component!`;
|
|
1589
|
+
return store;
|
|
1590
|
+
}
|
|
1561
1591
|
function useThree(selector = state => state, equalityFn) {
|
|
1562
|
-
|
|
1563
|
-
if (!useStore) throw `R3F hooks can only be used within the Canvas component!`;
|
|
1564
|
-
return useStore(selector, equalityFn);
|
|
1592
|
+
return useStore()(selector, equalityFn);
|
|
1565
1593
|
}
|
|
1566
1594
|
function useFrame(callback, renderPriority = 0) {
|
|
1567
|
-
const
|
|
1568
|
-
subscribe
|
|
1569
|
-
} = React__namespace.useContext(context).getState().internal; // Update ref
|
|
1595
|
+
const subscribe = useStore().getState().internal.subscribe; // Update ref
|
|
1570
1596
|
|
|
1571
1597
|
const ref = React__namespace.useRef(callback);
|
|
1572
|
-
React__namespace.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe
|
|
1598
|
+
React__namespace.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe on mount, unsubscribe on unmount
|
|
1573
1599
|
|
|
1574
|
-
React__namespace.useLayoutEffect(() =>
|
|
1575
|
-
const unsubscribe = subscribe(ref, renderPriority);
|
|
1576
|
-
return () => unsubscribe();
|
|
1577
|
-
}, [renderPriority, subscribe]);
|
|
1600
|
+
React__namespace.useLayoutEffect(() => subscribe(ref, renderPriority), [renderPriority]);
|
|
1578
1601
|
return null;
|
|
1579
1602
|
}
|
|
1580
1603
|
|
|
@@ -1629,6 +1652,11 @@ useLoader.preload = function (Proto, input, extensions) {
|
|
|
1629
1652
|
return useAsset.useAsset.preload(loadingFn(extensions), Proto, ...keys);
|
|
1630
1653
|
};
|
|
1631
1654
|
|
|
1655
|
+
useLoader.clear = function (Proto, input) {
|
|
1656
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
1657
|
+
return useAsset.useAsset.clear(Proto, ...keys);
|
|
1658
|
+
};
|
|
1659
|
+
|
|
1632
1660
|
const roots = new Map();
|
|
1633
1661
|
const modes = ['legacy', 'blocking', 'concurrent'];
|
|
1634
1662
|
const {
|
|
@@ -1832,4 +1860,5 @@ exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
|
1832
1860
|
exports.useFrame = useFrame;
|
|
1833
1861
|
exports.useGraph = useGraph;
|
|
1834
1862
|
exports.useLoader = useLoader;
|
|
1863
|
+
exports.useStore = useStore;
|
|
1835
1864
|
exports.useThree = useThree;
|
|
@@ -74,7 +74,7 @@ const is = {
|
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
function makeId(event) {
|
|
77
|
-
return (event.eventObject || event.object).uuid + '/' + event.index;
|
|
77
|
+
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
function removeInteractivity(store, object) {
|
|
@@ -306,7 +306,7 @@ function createEvents(store) {
|
|
|
306
306
|
Array.from(internal.hovered.values()).forEach(hoveredObj => {
|
|
307
307
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
308
308
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
309
|
-
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index)) {
|
|
309
|
+
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
310
310
|
const eventObject = hoveredObj.eventObject;
|
|
311
311
|
const handlers = eventObject.__r3f.handlers;
|
|
312
312
|
internal.hovered.delete(makeId(hoveredObj));
|
|
@@ -704,16 +704,18 @@ function createRenderer(roots) {
|
|
|
704
704
|
} // Auto-attach geometries and materials
|
|
705
705
|
|
|
706
706
|
|
|
707
|
-
if (
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
707
|
+
if (!('attachFns' in props)) {
|
|
708
|
+
if (name.endsWith('Geometry')) {
|
|
709
|
+
props = {
|
|
710
|
+
attach: 'geometry',
|
|
711
|
+
...props
|
|
712
|
+
};
|
|
713
|
+
} else if (name.endsWith('Material')) {
|
|
714
|
+
props = {
|
|
715
|
+
attach: 'material',
|
|
716
|
+
...props
|
|
717
|
+
};
|
|
718
|
+
}
|
|
717
719
|
} // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
|
|
718
720
|
// view yet. If the callback relies on references for instance, they won't be ready yet, this is
|
|
719
721
|
// why it passes "true" here
|
|
@@ -736,6 +738,14 @@ function createRenderer(roots) {
|
|
|
736
738
|
parentInstance[child.attachObject[0]][child.attachObject[1]] = child;
|
|
737
739
|
} else if (child.attach && !is.fun(child.attach)) {
|
|
738
740
|
parentInstance[child.attach] = child;
|
|
741
|
+
} else if (is.arr(child.attachFns)) {
|
|
742
|
+
const [attachFn] = child.attachFns;
|
|
743
|
+
|
|
744
|
+
if (is.str(attachFn) && is.fun(parentInstance[attachFn])) {
|
|
745
|
+
parentInstance[attachFn](child);
|
|
746
|
+
} else if (is.fun(attachFn)) {
|
|
747
|
+
attachFn(child, parentInstance);
|
|
748
|
+
}
|
|
739
749
|
} else if (child.isObject3D) {
|
|
740
750
|
// add in the usual parent-child way
|
|
741
751
|
parentInstance.add(child);
|
|
@@ -814,6 +824,14 @@ function createRenderer(roots) {
|
|
|
814
824
|
delete parentInstance[child.attachObject[0]][child.attachObject[1]];
|
|
815
825
|
} else if (child.attach && !is.fun(child.attach)) {
|
|
816
826
|
parentInstance[child.attach] = null;
|
|
827
|
+
} else if (is.arr(child.attachFns)) {
|
|
828
|
+
const [, detachFn] = child.attachFns;
|
|
829
|
+
|
|
830
|
+
if (is.str(detachFn) && is.fun(parentInstance[detachFn])) {
|
|
831
|
+
parentInstance[detachFn](child);
|
|
832
|
+
} else if (is.fun(detachFn)) {
|
|
833
|
+
detachFn(child, parentInstance);
|
|
834
|
+
}
|
|
817
835
|
} else if (child.isObject3D) {
|
|
818
836
|
var _child$__r3f;
|
|
819
837
|
|
|
@@ -826,7 +844,7 @@ function createRenderer(roots) {
|
|
|
826
844
|
// Never dispose of primitives because their state may be kept outside of React!
|
|
827
845
|
// In order for an object to be able to dispose it has to have
|
|
828
846
|
// - a dispose method,
|
|
829
|
-
// - it cannot be
|
|
847
|
+
// - it cannot be a <primitive object={...} />
|
|
830
848
|
// - it cannot be a THREE.Scene, because three has broken it's own api
|
|
831
849
|
//
|
|
832
850
|
// Since disposal is recursive, we can check the optional dispose arg, which will be undefined
|
|
@@ -855,7 +873,13 @@ function createRenderer(roots) {
|
|
|
855
873
|
|
|
856
874
|
|
|
857
875
|
if (shouldDispose && child.dispose && child.type !== 'Scene') {
|
|
858
|
-
scheduler.unstable_runWithPriority(scheduler.unstable_IdlePriority, () =>
|
|
876
|
+
scheduler.unstable_runWithPriority(scheduler.unstable_IdlePriority, () => {
|
|
877
|
+
try {
|
|
878
|
+
child.dispose();
|
|
879
|
+
} catch (e) {
|
|
880
|
+
/* ... */
|
|
881
|
+
}
|
|
882
|
+
});
|
|
859
883
|
}
|
|
860
884
|
|
|
861
885
|
invalidateInstance(parentInstance);
|
|
@@ -1163,6 +1187,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1163
1187
|
flat,
|
|
1164
1188
|
scene: prepare(new THREE__namespace.Scene()),
|
|
1165
1189
|
camera,
|
|
1190
|
+
controls: null,
|
|
1166
1191
|
raycaster,
|
|
1167
1192
|
clock,
|
|
1168
1193
|
mouse: new THREE__namespace.Vector2(),
|
|
@@ -1237,8 +1262,8 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1237
1262
|
internal: { ...internal,
|
|
1238
1263
|
// If this subscription was given a priority, it takes rendering into its own hands
|
|
1239
1264
|
// For that reason we switch off automatic rendering and increase the manual flag
|
|
1240
|
-
// As long as this flag is positive
|
|
1241
|
-
//
|
|
1265
|
+
// As long as this flag is positive there can be no internal rendering at all
|
|
1266
|
+
// because there could be multiple render subscriptions
|
|
1242
1267
|
priority: internal.priority + (priority > 0 ? 1 : 0),
|
|
1243
1268
|
// Register subscriber and sort layers from lowest to highest, meaning,
|
|
1244
1269
|
// highest priority renders last (on top of the other frames)
|
|
@@ -1558,23 +1583,21 @@ const Canvas = /*#__PURE__*/React__namespace.forwardRef(function Canvas({
|
|
|
1558
1583
|
}, fallback));
|
|
1559
1584
|
});
|
|
1560
1585
|
|
|
1586
|
+
function useStore() {
|
|
1587
|
+
const store = React__namespace.useContext(context);
|
|
1588
|
+
if (!store) throw `R3F hooks can only be used within the Canvas component!`;
|
|
1589
|
+
return store;
|
|
1590
|
+
}
|
|
1561
1591
|
function useThree(selector = state => state, equalityFn) {
|
|
1562
|
-
|
|
1563
|
-
if (!useStore) throw `R3F hooks can only be used within the Canvas component!`;
|
|
1564
|
-
return useStore(selector, equalityFn);
|
|
1592
|
+
return useStore()(selector, equalityFn);
|
|
1565
1593
|
}
|
|
1566
1594
|
function useFrame(callback, renderPriority = 0) {
|
|
1567
|
-
const
|
|
1568
|
-
subscribe
|
|
1569
|
-
} = React__namespace.useContext(context).getState().internal; // Update ref
|
|
1595
|
+
const subscribe = useStore().getState().internal.subscribe; // Update ref
|
|
1570
1596
|
|
|
1571
1597
|
const ref = React__namespace.useRef(callback);
|
|
1572
|
-
React__namespace.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe
|
|
1598
|
+
React__namespace.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe on mount, unsubscribe on unmount
|
|
1573
1599
|
|
|
1574
|
-
React__namespace.useLayoutEffect(() =>
|
|
1575
|
-
const unsubscribe = subscribe(ref, renderPriority);
|
|
1576
|
-
return () => unsubscribe();
|
|
1577
|
-
}, [renderPriority, subscribe]);
|
|
1600
|
+
React__namespace.useLayoutEffect(() => subscribe(ref, renderPriority), [renderPriority]);
|
|
1578
1601
|
return null;
|
|
1579
1602
|
}
|
|
1580
1603
|
|
|
@@ -1629,6 +1652,11 @@ useLoader.preload = function (Proto, input, extensions) {
|
|
|
1629
1652
|
return useAsset.useAsset.preload(loadingFn(extensions), Proto, ...keys);
|
|
1630
1653
|
};
|
|
1631
1654
|
|
|
1655
|
+
useLoader.clear = function (Proto, input) {
|
|
1656
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
1657
|
+
return useAsset.useAsset.clear(Proto, ...keys);
|
|
1658
|
+
};
|
|
1659
|
+
|
|
1632
1660
|
const roots = new Map();
|
|
1633
1661
|
const modes = ['legacy', 'blocking', 'concurrent'];
|
|
1634
1662
|
const {
|
|
@@ -1832,4 +1860,5 @@ exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
|
1832
1860
|
exports.useFrame = useFrame;
|
|
1833
1861
|
exports.useGraph = useGraph;
|
|
1834
1862
|
exports.useLoader = useLoader;
|
|
1863
|
+
exports.useStore = useStore;
|
|
1835
1864
|
exports.useThree = useThree;
|
|
@@ -40,7 +40,7 @@ const is = {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
function makeId(event) {
|
|
43
|
-
return (event.eventObject || event.object).uuid + '/' + event.index;
|
|
43
|
+
return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
function removeInteractivity(store, object) {
|
|
@@ -272,7 +272,7 @@ function createEvents(store) {
|
|
|
272
272
|
Array.from(internal.hovered.values()).forEach(hoveredObj => {
|
|
273
273
|
// When no objects were hit or the the hovered object wasn't found underneath the cursor
|
|
274
274
|
// we call onPointerOut and delete the object from the hovered-elements map
|
|
275
|
-
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index)) {
|
|
275
|
+
if (!hits.length || !hits.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
|
|
276
276
|
const eventObject = hoveredObj.eventObject;
|
|
277
277
|
const handlers = eventObject.__r3f.handlers;
|
|
278
278
|
internal.hovered.delete(makeId(hoveredObj));
|
|
@@ -670,16 +670,18 @@ function createRenderer(roots) {
|
|
|
670
670
|
} // Auto-attach geometries and materials
|
|
671
671
|
|
|
672
672
|
|
|
673
|
-
if (
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
673
|
+
if (!('attachFns' in props)) {
|
|
674
|
+
if (name.endsWith('Geometry')) {
|
|
675
|
+
props = {
|
|
676
|
+
attach: 'geometry',
|
|
677
|
+
...props
|
|
678
|
+
};
|
|
679
|
+
} else if (name.endsWith('Material')) {
|
|
680
|
+
props = {
|
|
681
|
+
attach: 'material',
|
|
682
|
+
...props
|
|
683
|
+
};
|
|
684
|
+
}
|
|
683
685
|
} // It should NOT call onUpdate on object instanciation, because it hasn't been added to the
|
|
684
686
|
// view yet. If the callback relies on references for instance, they won't be ready yet, this is
|
|
685
687
|
// why it passes "true" here
|
|
@@ -702,6 +704,14 @@ function createRenderer(roots) {
|
|
|
702
704
|
parentInstance[child.attachObject[0]][child.attachObject[1]] = child;
|
|
703
705
|
} else if (child.attach && !is.fun(child.attach)) {
|
|
704
706
|
parentInstance[child.attach] = child;
|
|
707
|
+
} else if (is.arr(child.attachFns)) {
|
|
708
|
+
const [attachFn] = child.attachFns;
|
|
709
|
+
|
|
710
|
+
if (is.str(attachFn) && is.fun(parentInstance[attachFn])) {
|
|
711
|
+
parentInstance[attachFn](child);
|
|
712
|
+
} else if (is.fun(attachFn)) {
|
|
713
|
+
attachFn(child, parentInstance);
|
|
714
|
+
}
|
|
705
715
|
} else if (child.isObject3D) {
|
|
706
716
|
// add in the usual parent-child way
|
|
707
717
|
parentInstance.add(child);
|
|
@@ -780,6 +790,14 @@ function createRenderer(roots) {
|
|
|
780
790
|
delete parentInstance[child.attachObject[0]][child.attachObject[1]];
|
|
781
791
|
} else if (child.attach && !is.fun(child.attach)) {
|
|
782
792
|
parentInstance[child.attach] = null;
|
|
793
|
+
} else if (is.arr(child.attachFns)) {
|
|
794
|
+
const [, detachFn] = child.attachFns;
|
|
795
|
+
|
|
796
|
+
if (is.str(detachFn) && is.fun(parentInstance[detachFn])) {
|
|
797
|
+
parentInstance[detachFn](child);
|
|
798
|
+
} else if (is.fun(detachFn)) {
|
|
799
|
+
detachFn(child, parentInstance);
|
|
800
|
+
}
|
|
783
801
|
} else if (child.isObject3D) {
|
|
784
802
|
var _child$__r3f;
|
|
785
803
|
|
|
@@ -792,7 +810,7 @@ function createRenderer(roots) {
|
|
|
792
810
|
// Never dispose of primitives because their state may be kept outside of React!
|
|
793
811
|
// In order for an object to be able to dispose it has to have
|
|
794
812
|
// - a dispose method,
|
|
795
|
-
// - it cannot be
|
|
813
|
+
// - it cannot be a <primitive object={...} />
|
|
796
814
|
// - it cannot be a THREE.Scene, because three has broken it's own api
|
|
797
815
|
//
|
|
798
816
|
// Since disposal is recursive, we can check the optional dispose arg, which will be undefined
|
|
@@ -821,7 +839,13 @@ function createRenderer(roots) {
|
|
|
821
839
|
|
|
822
840
|
|
|
823
841
|
if (shouldDispose && child.dispose && child.type !== 'Scene') {
|
|
824
|
-
unstable_runWithPriority(unstable_IdlePriority, () =>
|
|
842
|
+
unstable_runWithPriority(unstable_IdlePriority, () => {
|
|
843
|
+
try {
|
|
844
|
+
child.dispose();
|
|
845
|
+
} catch (e) {
|
|
846
|
+
/* ... */
|
|
847
|
+
}
|
|
848
|
+
});
|
|
825
849
|
}
|
|
826
850
|
|
|
827
851
|
invalidateInstance(parentInstance);
|
|
@@ -1129,6 +1153,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1129
1153
|
flat,
|
|
1130
1154
|
scene: prepare(new THREE.Scene()),
|
|
1131
1155
|
camera,
|
|
1156
|
+
controls: null,
|
|
1132
1157
|
raycaster,
|
|
1133
1158
|
clock,
|
|
1134
1159
|
mouse: new THREE.Vector2(),
|
|
@@ -1203,8 +1228,8 @@ const createStore = (applyProps, invalidate, advance, props) => {
|
|
|
1203
1228
|
internal: { ...internal,
|
|
1204
1229
|
// If this subscription was given a priority, it takes rendering into its own hands
|
|
1205
1230
|
// For that reason we switch off automatic rendering and increase the manual flag
|
|
1206
|
-
// As long as this flag is positive
|
|
1207
|
-
//
|
|
1231
|
+
// As long as this flag is positive there can be no internal rendering at all
|
|
1232
|
+
// because there could be multiple render subscriptions
|
|
1208
1233
|
priority: internal.priority + (priority > 0 ? 1 : 0),
|
|
1209
1234
|
// Register subscriber and sort layers from lowest to highest, meaning,
|
|
1210
1235
|
// highest priority renders last (on top of the other frames)
|
|
@@ -1524,23 +1549,21 @@ const Canvas = /*#__PURE__*/React.forwardRef(function Canvas({
|
|
|
1524
1549
|
}, fallback));
|
|
1525
1550
|
});
|
|
1526
1551
|
|
|
1552
|
+
function useStore() {
|
|
1553
|
+
const store = React.useContext(context);
|
|
1554
|
+
if (!store) throw `R3F hooks can only be used within the Canvas component!`;
|
|
1555
|
+
return store;
|
|
1556
|
+
}
|
|
1527
1557
|
function useThree(selector = state => state, equalityFn) {
|
|
1528
|
-
|
|
1529
|
-
if (!useStore) throw `R3F hooks can only be used within the Canvas component!`;
|
|
1530
|
-
return useStore(selector, equalityFn);
|
|
1558
|
+
return useStore()(selector, equalityFn);
|
|
1531
1559
|
}
|
|
1532
1560
|
function useFrame(callback, renderPriority = 0) {
|
|
1533
|
-
const
|
|
1534
|
-
subscribe
|
|
1535
|
-
} = React.useContext(context).getState().internal; // Update ref
|
|
1561
|
+
const subscribe = useStore().getState().internal.subscribe; // Update ref
|
|
1536
1562
|
|
|
1537
1563
|
const ref = React.useRef(callback);
|
|
1538
|
-
React.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe
|
|
1564
|
+
React.useLayoutEffect(() => void (ref.current = callback), [callback]); // Subscribe on mount, unsubscribe on unmount
|
|
1539
1565
|
|
|
1540
|
-
React.useLayoutEffect(() =>
|
|
1541
|
-
const unsubscribe = subscribe(ref, renderPriority);
|
|
1542
|
-
return () => unsubscribe();
|
|
1543
|
-
}, [renderPriority, subscribe]);
|
|
1566
|
+
React.useLayoutEffect(() => subscribe(ref, renderPriority), [renderPriority]);
|
|
1544
1567
|
return null;
|
|
1545
1568
|
}
|
|
1546
1569
|
|
|
@@ -1595,6 +1618,11 @@ useLoader.preload = function (Proto, input, extensions) {
|
|
|
1595
1618
|
return useAsset.preload(loadingFn(extensions), Proto, ...keys);
|
|
1596
1619
|
};
|
|
1597
1620
|
|
|
1621
|
+
useLoader.clear = function (Proto, input) {
|
|
1622
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
1623
|
+
return useAsset.clear(Proto, ...keys);
|
|
1624
|
+
};
|
|
1625
|
+
|
|
1598
1626
|
const roots = new Map();
|
|
1599
1627
|
const modes = ['legacy', 'blocking', 'concurrent'];
|
|
1600
1628
|
const {
|
|
@@ -1777,4 +1805,4 @@ reconciler.injectIntoDevTools({
|
|
|
1777
1805
|
version: '17.0.2'
|
|
1778
1806
|
});
|
|
1779
1807
|
|
|
1780
|
-
export { Canvas, threeTypes as ReactThreeFiber, roots as _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, context, createPortal, dispose, createPointerEvents as events, extend, invalidate, reconciler, render, unmountComponentAtNode, useFrame, useGraph, useLoader, useThree };
|
|
1808
|
+
export { Canvas, threeTypes as ReactThreeFiber, roots as _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, context, createPortal, dispose, createPointerEvents as events, extend, invalidate, reconciler, render, unmountComponentAtNode, useFrame, useGraph, useLoader, useStore, useThree };
|