@react-three/fiber 10.0.0-canary.98da52a → 10.0.0-canary.a056612
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/dist/extension.cjs +8 -8
- package/dist/extension.d.cts +4 -4
- package/dist/extension.d.mts +4 -4
- package/dist/extension.d.ts +4 -4
- package/dist/extension.mjs +1 -1
- package/dist/index.cjs +13 -13
- package/dist/index.d.cts +6 -6
- package/dist/index.d.mts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.mjs +3 -3
- package/dist/legacy.cjs +13 -13
- package/dist/legacy.d.cts +10 -7
- package/dist/legacy.d.mts +10 -7
- package/dist/legacy.d.ts +10 -7
- package/dist/legacy.mjs +4 -4
- package/dist/shared/{fiber.DNehrxK5.d.ts → fiber.3jeDXXYd.d.mts} +150 -457
- package/dist/shared/{fiber.11sXr8Eb.d.cts → fiber.B_KQAb3I.d.ts} +150 -457
- package/dist/shared/{fiber.CT-cCVjA.mjs → fiber.BdXKJXa0.mjs} +2116 -1559
- package/dist/shared/{fiber.Cn-vxHMl.cjs → fiber.Bzw3s8zU.cjs} +2228 -1671
- package/dist/shared/{fiber.DAl4H27x.d.cts → fiber.C6hitYDY.d.cts} +1 -1
- package/dist/shared/{fiber.I5Q4dVvl.d.cts → fiber.C_MFx7We.d.cts} +479 -20
- package/dist/shared/{fiber.I5Q4dVvl.d.mts → fiber.C_MFx7We.d.mts} +479 -20
- package/dist/shared/{fiber.I5Q4dVvl.d.ts → fiber.C_MFx7We.d.ts} +479 -20
- package/dist/shared/{fiber.khFlPHPf.cjs → fiber.CsZ092z_.cjs} +84 -55
- package/dist/shared/{fiber.BU0vBHc9.d.mts → fiber.D4fD6H74.d.mts} +1 -1
- package/dist/shared/{fiber.B0oukOFO.mjs → fiber.DlH05gco.mjs} +84 -57
- package/dist/shared/{fiber.Cx-UAmMb.d.ts → fiber.YgTUGbja.d.ts} +1 -1
- package/dist/shared/{fiber.TWXdbcWP.d.mts → fiber.fR3DaJb1.d.cts} +150 -457
- package/dist/webgpu/index.cjs +13 -13
- package/dist/webgpu/index.d.cts +5 -5
- package/dist/webgpu/index.d.mts +5 -5
- package/dist/webgpu/index.d.ts +5 -5
- package/dist/webgpu/index.mjs +4 -4
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { n as notifyDepreciated,
|
|
2
|
+
import { n as notifyDepreciated, i as isDevelopment, h as detachRootExtensions, j as attachRootExtensions, d as useIsomorphicLayoutEffect, c as context, a as useThree, u as useStore, k as unstageTextures, l as stageTextures, e as useMutableCallback, b as useFrame, f as useBridge, m as useGate, o as notifyAlpha, E as ErrorBoundary, B as Block, p as notifyRootExtensionsHmr } from './fiber.DlH05gco.mjs';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import React__default, { useRef, useMemo, useLayoutEffect, useEffect, useImperativeHandle, useCallback, useState } from 'react';
|
|
5
5
|
import useMeasure from 'react-use-measure';
|
|
@@ -107,6 +107,20 @@ function updateFrustum(camera, frustum) {
|
|
|
107
107
|
target.setFromProjectionMatrix(frustumMatrix);
|
|
108
108
|
return target;
|
|
109
109
|
}
|
|
110
|
+
function computeInitialSize(canvas, size) {
|
|
111
|
+
if (!size && typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
112
|
+
const { width, height, top, left } = canvas.parentElement.getBoundingClientRect();
|
|
113
|
+
return { width, height, top, left };
|
|
114
|
+
} else if (!size && typeof OffscreenCanvas !== "undefined" && canvas instanceof OffscreenCanvas) {
|
|
115
|
+
return {
|
|
116
|
+
width: canvas.width,
|
|
117
|
+
height: canvas.height,
|
|
118
|
+
top: 0,
|
|
119
|
+
left: 0
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return { width: 0, height: 0, top: 0, left: 0, ...size };
|
|
123
|
+
}
|
|
110
124
|
|
|
111
125
|
const REACT_INTERNAL_PROPS = ["children", "key", "ref"];
|
|
112
126
|
function findInitialRoot(instance) {
|
|
@@ -174,6 +188,7 @@ function prepare(target, root, type, props) {
|
|
|
174
188
|
object,
|
|
175
189
|
eventCount: 0,
|
|
176
190
|
handlers: {},
|
|
191
|
+
previousVisible: void 0,
|
|
177
192
|
isHidden: false
|
|
178
193
|
};
|
|
179
194
|
if (object) object.__r3f = instance;
|
|
@@ -422,6 +437,28 @@ const VISIBILITY_EVENT_REGEX = /^on(Framed|Occluded|Visible)$/;
|
|
|
422
437
|
const INDEX_REGEX = /-\d+$/;
|
|
423
438
|
const MEMOIZED_PROTOTYPES = /* @__PURE__ */ new Map();
|
|
424
439
|
const colorMaps = ["map", "emissiveMap", "sheenColorMap", "specularColorMap", "envMap"];
|
|
440
|
+
const programProps = /* @__PURE__ */ new Set([
|
|
441
|
+
"transparent",
|
|
442
|
+
"vertexColors",
|
|
443
|
+
"flatShading",
|
|
444
|
+
"fog",
|
|
445
|
+
// Culling is live, but DOUBLE_SIDED / FLIP_SIDED normal flipping is compiled in
|
|
446
|
+
"side",
|
|
447
|
+
"alphaHash",
|
|
448
|
+
"premultipliedAlpha",
|
|
449
|
+
// Both feed the OPAQUE define when the material is not transparent
|
|
450
|
+
"blending",
|
|
451
|
+
"alphaToCoverage",
|
|
452
|
+
"dithering",
|
|
453
|
+
"sizeAttenuation",
|
|
454
|
+
"combine",
|
|
455
|
+
"normalMapType",
|
|
456
|
+
"depthPacking"
|
|
457
|
+
]);
|
|
458
|
+
function changesProgram(root, key, previous, next) {
|
|
459
|
+
if (!root?.isMaterial || previous === next) return false;
|
|
460
|
+
return programProps.has(key) || isTexture(previous) !== isTexture(next);
|
|
461
|
+
}
|
|
425
462
|
function resolve(root, key) {
|
|
426
463
|
if (!key.includes("-")) return { root, key, target: root[key] };
|
|
427
464
|
if (key in root) return { root, key, target: root[key] };
|
|
@@ -452,6 +489,7 @@ function attach(parent, child) {
|
|
|
452
489
|
const { root, key } = resolve(parent.object, child.props.attach);
|
|
453
490
|
child.previousAttach = root[key];
|
|
454
491
|
root[key] = child.object;
|
|
492
|
+
if (changesProgram(root, key, child.previousAttach, child.object)) root.needsUpdate = true;
|
|
455
493
|
} else if (is.fun(child.props.attach)) {
|
|
456
494
|
child.previousAttach = child.props.attach(parent.object, child.object);
|
|
457
495
|
}
|
|
@@ -462,6 +500,7 @@ function detach(parent, child) {
|
|
|
462
500
|
const previous = child.previousAttach;
|
|
463
501
|
if (previous === void 0) delete root[key];
|
|
464
502
|
else root[key] = previous;
|
|
503
|
+
if (changesProgram(root, key, child.object, previous)) root.needsUpdate = true;
|
|
465
504
|
} else {
|
|
466
505
|
child.previousAttach?.(parent.object, child.object);
|
|
467
506
|
}
|
|
@@ -541,6 +580,10 @@ function applyProps(object, props) {
|
|
|
541
580
|
}
|
|
542
581
|
continue;
|
|
543
582
|
}
|
|
583
|
+
if (prop === "visible" && instance?.isHidden && instance.previousVisible !== void 0) {
|
|
584
|
+
instance.previousVisible = value;
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
544
587
|
let { root, key, target } = resolve(object, prop);
|
|
545
588
|
if (target === void 0 && (typeof root !== "object" || root === null)) {
|
|
546
589
|
throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`);
|
|
@@ -576,9 +619,12 @@ function applyProps(object, props) {
|
|
|
576
619
|
}
|
|
577
620
|
} else {
|
|
578
621
|
if (key === "material") assertNodeMaterialSupported(rootState, value);
|
|
622
|
+
const previous = root[key];
|
|
579
623
|
root[key] = value;
|
|
580
624
|
if (key.endsWith("Node") && root.isMaterial) {
|
|
581
625
|
root.needsUpdate = true;
|
|
626
|
+
} else if (changesProgram(root, key, previous, value)) {
|
|
627
|
+
root.needsUpdate = true;
|
|
582
628
|
}
|
|
583
629
|
const three = rootState && getThree();
|
|
584
630
|
if (three && rootState.renderer?.outputColorSpace === three.SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
@@ -619,468 +665,425 @@ function applyProps(object, props) {
|
|
|
619
665
|
return object;
|
|
620
666
|
}
|
|
621
667
|
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
if (!loader) {
|
|
628
|
-
loader = new Proto();
|
|
629
|
-
memoizedLoaders.set(Proto, loader);
|
|
630
|
-
}
|
|
631
|
-
return loader;
|
|
632
|
-
}
|
|
633
|
-
return Proto;
|
|
634
|
-
}
|
|
635
|
-
function loadingFn(extensions, onProgress) {
|
|
636
|
-
return function(Proto, input) {
|
|
637
|
-
const loader = getLoader(Proto);
|
|
638
|
-
if (extensions) extensions(loader);
|
|
639
|
-
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
640
|
-
return loader.loadAsync(input, onProgress).then((data) => {
|
|
641
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
642
|
-
return data;
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
return new Promise(
|
|
646
|
-
(res, reject) => loader.load(
|
|
647
|
-
input,
|
|
648
|
-
(data) => {
|
|
649
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
650
|
-
res(data);
|
|
651
|
-
},
|
|
652
|
-
onProgress,
|
|
653
|
-
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
654
|
-
)
|
|
655
|
-
);
|
|
656
|
-
};
|
|
657
|
-
}
|
|
658
|
-
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
659
|
-
const inputs = Array.isArray(input) ? input : [input];
|
|
660
|
-
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
661
|
-
const fn = loadingFn(extensions, onProgress);
|
|
662
|
-
const results = cacheKeys.map(
|
|
663
|
-
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
664
|
-
);
|
|
665
|
-
const stableRef = useRef(null);
|
|
666
|
-
const previous = stableRef.current;
|
|
667
|
-
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
668
|
-
stableRef.current = stable;
|
|
669
|
-
return Array.isArray(input) ? stable : stable[0];
|
|
668
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
669
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
670
|
+
if (!stack) return false;
|
|
671
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
672
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
670
673
|
}
|
|
671
|
-
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
672
|
-
const inputs = Array.isArray(input) ? input : [input];
|
|
673
|
-
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
674
|
-
cacheKeys.forEach(
|
|
675
|
-
(key, index) => preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
676
|
-
);
|
|
677
|
-
};
|
|
678
|
-
useLoader.clear = function(loader, input, cacheKey) {
|
|
679
|
-
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
680
|
-
cacheKeys.forEach((key) => clear([loader, key]));
|
|
681
|
-
};
|
|
682
|
-
useLoader.loader = getLoader;
|
|
683
674
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
if (typeof input === "string") return input;
|
|
692
|
-
if (Array.isArray(input)) return input.join("\0");
|
|
693
|
-
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
694
|
-
}
|
|
695
|
-
function allUrlsCached(urls, textureCache) {
|
|
696
|
-
return urls.every((url) => textureCache.has(url));
|
|
675
|
+
function updateSize(state, size, imperative) {
|
|
676
|
+
state.set((current) => ({
|
|
677
|
+
size,
|
|
678
|
+
viewport: { ...current.viewport, ...current.viewport.getCurrentViewport(current.camera, void 0, size) },
|
|
679
|
+
_sizeImperative: imperative
|
|
680
|
+
}));
|
|
681
|
+
state.invalidate();
|
|
697
682
|
}
|
|
698
|
-
function
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
return input.map((url) => textureCache.get(url));
|
|
703
|
-
} else {
|
|
704
|
-
const result = {};
|
|
705
|
-
const objInput = input;
|
|
706
|
-
for (const key in objInput) {
|
|
707
|
-
result[key] = textureCache.get(objInput[key]);
|
|
708
|
-
}
|
|
709
|
-
return result;
|
|
710
|
-
}
|
|
683
|
+
function configureSize(store, size) {
|
|
684
|
+
const state = store.getState();
|
|
685
|
+
if (state._sizeImperative || is.equ(size, state.size, { objects: "shallow", strict: false })) return;
|
|
686
|
+
updateSize(state, size, false);
|
|
711
687
|
}
|
|
712
|
-
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
if (IsObject(stableInput)) {
|
|
736
|
-
const keyed = {};
|
|
737
|
-
const textureArray = loadedTextures;
|
|
738
|
-
let i = 0;
|
|
739
|
-
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
740
|
-
return keyed;
|
|
741
|
-
} else {
|
|
742
|
-
return loadedTextures;
|
|
743
|
-
}
|
|
744
|
-
}, [stableInput, loadedTextures, cachedResult]);
|
|
745
|
-
useLayoutEffect(() => {
|
|
746
|
-
if (cachedResult) return;
|
|
747
|
-
if (onLoadCalledForRef.current === inputKey) return;
|
|
748
|
-
onLoadCalledForRef.current = inputKey;
|
|
749
|
-
onLoadRef.current?.(mappedTextures);
|
|
750
|
-
}, [cachedResult, mappedTextures, inputKey]);
|
|
751
|
-
useEffect(() => {
|
|
752
|
-
if (cachedResult) return;
|
|
753
|
-
if ("initTexture" in renderer) {
|
|
754
|
-
let textureArray = [];
|
|
755
|
-
if (Array.isArray(loadedTextures)) {
|
|
756
|
-
textureArray = loadedTextures;
|
|
757
|
-
} else if (loadedTextures.isTexture) {
|
|
758
|
-
textureArray = [loadedTextures];
|
|
759
|
-
} else if (IsObject(loadedTextures)) {
|
|
760
|
-
textureArray = Object.values(loadedTextures);
|
|
688
|
+
const createStore = (invalidate, advance) => {
|
|
689
|
+
const rootStore = createWithEqualityFn((set, get) => {
|
|
690
|
+
let position;
|
|
691
|
+
let defaultTarget;
|
|
692
|
+
let tempTarget;
|
|
693
|
+
function getCurrentViewport(camera = get().camera, target = void 0, size = get().size) {
|
|
694
|
+
const { Vector3 } = getThree();
|
|
695
|
+
position ?? (position = new Vector3());
|
|
696
|
+
defaultTarget ?? (defaultTarget = new Vector3());
|
|
697
|
+
tempTarget ?? (tempTarget = new Vector3());
|
|
698
|
+
target ?? (target = defaultTarget);
|
|
699
|
+
const { width, height, top, left } = size;
|
|
700
|
+
const aspect = width / height;
|
|
701
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
702
|
+
else tempTarget.set(...target);
|
|
703
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
704
|
+
if (isOrthographicCamera(camera)) {
|
|
705
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
706
|
+
} else {
|
|
707
|
+
const fov = camera.fov * Math.PI / 180;
|
|
708
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
709
|
+
const w = h * (width / height);
|
|
710
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
761
711
|
}
|
|
762
|
-
textureArray.forEach((texture) => {
|
|
763
|
-
if (texture?.isTexture) {
|
|
764
|
-
renderer.initTexture(texture);
|
|
765
|
-
}
|
|
766
|
-
});
|
|
767
712
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
713
|
+
let performanceTimeout = void 0;
|
|
714
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
715
|
+
const rootState = {
|
|
716
|
+
set,
|
|
717
|
+
get,
|
|
718
|
+
// Mock objects that have to be configured
|
|
719
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
720
|
+
primaryStore: null,
|
|
721
|
+
gl: null,
|
|
722
|
+
renderer: null,
|
|
723
|
+
camera: null,
|
|
724
|
+
// frustum, pointer and mouse are three objects; configure() creates them with the renderer
|
|
725
|
+
frustum: null,
|
|
726
|
+
autoUpdateFrustum: true,
|
|
727
|
+
raycaster: null,
|
|
728
|
+
events: {
|
|
729
|
+
priority: 1,
|
|
730
|
+
enabled: true,
|
|
731
|
+
connected: false,
|
|
732
|
+
frameTimedRaycasts: true,
|
|
733
|
+
alwaysFireOnScroll: true,
|
|
734
|
+
updateOnFrame: false
|
|
735
|
+
},
|
|
736
|
+
scene: null,
|
|
737
|
+
rootScene: null,
|
|
738
|
+
xr: null,
|
|
739
|
+
inspector: null,
|
|
740
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
741
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
742
|
+
textureColorSpace: "srgb",
|
|
743
|
+
// THREE.SRGBColorSpace
|
|
744
|
+
isLegacy: false,
|
|
745
|
+
webGPUSupported: false,
|
|
746
|
+
isNative: false,
|
|
747
|
+
controls: null,
|
|
748
|
+
pointer: null,
|
|
749
|
+
mouse: null,
|
|
750
|
+
frameloop: "always",
|
|
751
|
+
onPointerMissed: void 0,
|
|
752
|
+
onDragOverMissed: void 0,
|
|
753
|
+
onDropMissed: void 0,
|
|
754
|
+
performance: {
|
|
755
|
+
current: 1,
|
|
756
|
+
min: 0.5,
|
|
757
|
+
max: 1,
|
|
758
|
+
debounce: 200,
|
|
759
|
+
regress: () => {
|
|
760
|
+
const state2 = get();
|
|
761
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
762
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
763
|
+
performanceTimeout = setTimeout(
|
|
764
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
765
|
+
state2.performance.debounce
|
|
766
|
+
);
|
|
783
767
|
}
|
|
784
|
-
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
785
|
-
}
|
|
786
|
-
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
787
|
-
});
|
|
788
|
-
unstageTextures(
|
|
789
|
-
store,
|
|
790
|
-
urlTextureMap.map(([url]) => url)
|
|
791
|
-
);
|
|
792
|
-
return () => store.setState((state) => {
|
|
793
|
-
const refs = new Map(state._textureRefs);
|
|
794
|
-
for (const [url] of urlTextureMap) {
|
|
795
|
-
const next = (refs.get(url) ?? 0) - 1;
|
|
796
|
-
if (next <= 0) refs.delete(url);
|
|
797
|
-
else refs.set(url, next);
|
|
798
|
-
}
|
|
799
|
-
return { _textureRefs: refs };
|
|
800
|
-
});
|
|
801
|
-
}, [cache, stableInput, mappedTextures, store]);
|
|
802
|
-
if (cache && !cachedResult) stageTextures(store, urlTextureEntries(stableInput, mappedTextures));
|
|
803
|
-
return mappedTextures;
|
|
804
|
-
}
|
|
805
|
-
function urlTextureEntries(input, textures) {
|
|
806
|
-
if (typeof input === "string") return [[input, textures]];
|
|
807
|
-
if (Array.isArray(input)) return input.map((url, i) => [url, textures[i]]);
|
|
808
|
-
const record = textures;
|
|
809
|
-
return Object.keys(input).map((key) => [input[key], record[key]]);
|
|
810
|
-
}
|
|
811
|
-
useTexture.preload = (url) => {
|
|
812
|
-
whenThree().then((three) => useLoader.preload(three.TextureLoader, url));
|
|
813
|
-
};
|
|
814
|
-
useTexture.clear = (input) => {
|
|
815
|
-
if (hasThree()) useLoader.clear(getThree().TextureLoader, input);
|
|
816
|
-
};
|
|
817
|
-
const Texture = ({
|
|
818
|
-
children,
|
|
819
|
-
input,
|
|
820
|
-
onLoad,
|
|
821
|
-
cache
|
|
822
|
-
}) => {
|
|
823
|
-
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
824
|
-
const ret = useTexture(input, options);
|
|
825
|
-
return /* @__PURE__ */ jsx(Fragment, { children: children?.(ret) });
|
|
826
|
-
};
|
|
827
|
-
|
|
828
|
-
function useTextures(selector) {
|
|
829
|
-
const store = useStore();
|
|
830
|
-
const registry = useMemo(() => {
|
|
831
|
-
const getState = store.getState;
|
|
832
|
-
const setState = store.setState;
|
|
833
|
-
const getOne = (key) => getState().textures.get(key);
|
|
834
|
-
return {
|
|
835
|
-
get all() {
|
|
836
|
-
return getState().textures;
|
|
837
768
|
},
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
769
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
770
|
+
viewport: {
|
|
771
|
+
initialDpr: 0,
|
|
772
|
+
dpr: 0,
|
|
773
|
+
width: 0,
|
|
774
|
+
height: 0,
|
|
775
|
+
top: 0,
|
|
776
|
+
left: 0,
|
|
777
|
+
aspect: 0,
|
|
778
|
+
distance: 0,
|
|
779
|
+
factor: 0,
|
|
780
|
+
getCurrentViewport
|
|
844
781
|
},
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
if (
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
782
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
783
|
+
setSize: (width, height, top, left) => {
|
|
784
|
+
const state2 = get();
|
|
785
|
+
if (width === void 0) {
|
|
786
|
+
if (state2._sizeProps) {
|
|
787
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
788
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
789
|
+
const currentSize = state2.size;
|
|
790
|
+
const newSize = {
|
|
791
|
+
width: propW ?? currentSize.width,
|
|
792
|
+
height: propH ?? currentSize.height,
|
|
793
|
+
top: currentSize.top,
|
|
794
|
+
left: currentSize.left
|
|
795
|
+
};
|
|
796
|
+
updateSize(state2, newSize, false);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
853
799
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
},
|
|
857
|
-
dispose(key, options) {
|
|
858
|
-
const state = getState();
|
|
859
|
-
const refs = state._textureRefs.get(key) ?? 0;
|
|
860
|
-
if (refs > 0 && !options?.force) {
|
|
861
|
-
console.warn(
|
|
862
|
-
`[useTextures] "${key}" still has ${refs} active reference(s); skipping dispose. Pass { force: true } to override.`
|
|
863
|
-
);
|
|
864
|
-
return false;
|
|
800
|
+
set({ _sizeImperative: false });
|
|
801
|
+
return;
|
|
865
802
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
return { textures, _textureRefs: nextRefs };
|
|
873
|
-
});
|
|
874
|
-
return true;
|
|
803
|
+
const w = width;
|
|
804
|
+
const h = height ?? width;
|
|
805
|
+
const t = top ?? state2.size.top;
|
|
806
|
+
const l = left ?? state2.size.left;
|
|
807
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
808
|
+
updateSize(state2, size, true);
|
|
875
809
|
},
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
810
|
+
setDpr: (dpr) => set((state2) => {
|
|
811
|
+
const resolved = calculateDpr(dpr);
|
|
812
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
813
|
+
}),
|
|
814
|
+
setFrameloop: (frameloop = "always") => {
|
|
815
|
+
const rootId = get().internal.rootId;
|
|
816
|
+
if (rootId) getScheduler().setRootFrameloop(rootId, frameloop);
|
|
817
|
+
set(() => ({ frameloop }));
|
|
818
|
+
},
|
|
819
|
+
setError: (error) => set(() => ({ error })),
|
|
820
|
+
error: null,
|
|
821
|
+
//* Texture registry (useTextures) ==============================
|
|
822
|
+
// TSL fields (uniforms, nodes, ..., renderPipeline) are added by @react-three/tsl's root extension.
|
|
823
|
+
textures: /* @__PURE__ */ new Map(),
|
|
824
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
825
|
+
_sizeImperative: false,
|
|
826
|
+
_sizeProps: null,
|
|
827
|
+
previousRoot: void 0,
|
|
828
|
+
internal: {
|
|
829
|
+
// Events
|
|
830
|
+
interaction: [],
|
|
831
|
+
subscribers: [],
|
|
832
|
+
// Per-pointer state (new unified structure)
|
|
833
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
834
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
835
|
+
lastEvent: React.createRef(),
|
|
836
|
+
// Deprecated but kept for backwards compatibility
|
|
837
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
838
|
+
initialClick: [0, 0],
|
|
839
|
+
initialHits: [],
|
|
840
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
841
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
842
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
843
|
+
// Occlusion system (WebGPU only)
|
|
844
|
+
occlusionEnabled: false,
|
|
845
|
+
occlusionObserver: null,
|
|
846
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
847
|
+
helperGroup: null,
|
|
848
|
+
// Updates
|
|
849
|
+
active: false,
|
|
850
|
+
frames: 0,
|
|
851
|
+
priority: 0,
|
|
852
|
+
subscribe: (ref, priority, store) => {
|
|
853
|
+
const internal = get().internal;
|
|
854
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
855
|
+
internal.subscribers.push({ ref, priority, store });
|
|
856
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
857
|
+
return () => {
|
|
858
|
+
const internal2 = get().internal;
|
|
859
|
+
if (internal2?.subscribers) {
|
|
860
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
861
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
},
|
|
865
|
+
// Renderer Storage (single source of truth)
|
|
866
|
+
actualRenderer: null,
|
|
867
|
+
// The renderer support configure() loads for this root
|
|
868
|
+
support: null,
|
|
869
|
+
// Scheduler for useFrameNext (initialized in loop.ts)
|
|
870
|
+
scheduler: null,
|
|
871
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
872
|
+
renderOverride: null
|
|
879
873
|
}
|
|
880
874
|
};
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
875
|
+
return rootState;
|
|
876
|
+
});
|
|
877
|
+
const state = rootStore.getState();
|
|
878
|
+
Object.defineProperty(state, "gl", {
|
|
879
|
+
get() {
|
|
880
|
+
const currentState = rootStore.getState();
|
|
881
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
882
|
+
const stack = new Error().stack || "";
|
|
883
|
+
if (!isInternalRendererAccess(stack)) {
|
|
884
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
885
|
+
notifyDepreciated({
|
|
886
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
887
|
+
body: "Please use state.renderer instead. state.gl is deprecated and will be removed in future versions.\n\nFor backwards compatibility, state.gl currently maps to state.renderer, but this may cause issues with libraries expecting WebGLRenderer.\n\nAccessed from:\n" + cleanedStack
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
return currentState.internal.actualRenderer;
|
|
892
|
+
},
|
|
893
|
+
set(value) {
|
|
894
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
895
|
+
},
|
|
896
|
+
enumerable: true,
|
|
897
|
+
configurable: true
|
|
898
|
+
});
|
|
899
|
+
Object.defineProperty(state, "renderer", {
|
|
900
|
+
get() {
|
|
901
|
+
return rootStore.getState().internal.actualRenderer;
|
|
902
|
+
},
|
|
903
|
+
set(value) {
|
|
904
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
905
|
+
},
|
|
906
|
+
enumerable: true,
|
|
907
|
+
configurable: true
|
|
908
|
+
});
|
|
909
|
+
let oldScene = state.scene;
|
|
910
|
+
rootStore.subscribe(() => {
|
|
911
|
+
const currentState = rootStore.getState();
|
|
912
|
+
const { scene, rootScene, set } = currentState;
|
|
913
|
+
if (scene !== oldScene) {
|
|
914
|
+
oldScene = scene;
|
|
915
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
916
|
+
set({ rootScene: scene });
|
|
917
|
+
}
|
|
905
918
|
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
919
|
+
});
|
|
920
|
+
let oldSize = state.size;
|
|
921
|
+
let oldDpr = state.viewport.dpr;
|
|
922
|
+
let oldCamera = state.camera;
|
|
923
|
+
rootStore.subscribe(() => {
|
|
924
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
925
|
+
const actualRenderer = internal.actualRenderer;
|
|
926
|
+
const canvasTarget = internal.canvasTarget;
|
|
927
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
928
|
+
oldSize = size;
|
|
929
|
+
oldDpr = viewport.dpr;
|
|
930
|
+
updateCamera(camera, size);
|
|
931
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
932
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
933
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
934
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
935
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
936
|
+
}
|
|
937
|
+
if (camera !== oldCamera) {
|
|
938
|
+
oldCamera = camera;
|
|
939
|
+
const { rootScene } = rootStore.getState();
|
|
940
|
+
if (camera && rootScene && !camera.parent) {
|
|
941
|
+
rootScene.add(camera);
|
|
942
|
+
}
|
|
943
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
944
|
+
const currentState = rootStore.getState();
|
|
945
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
946
|
+
updateFrustum(camera, currentState.frustum);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
rootStore.subscribe((state2) => {
|
|
951
|
+
if (state2.internal.active) invalidate(state2);
|
|
952
|
+
});
|
|
953
|
+
return rootStore;
|
|
926
954
|
};
|
|
927
955
|
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
const
|
|
931
|
-
const
|
|
932
|
-
const
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
956
|
+
const shallowLoose$1 = { objects: "shallow", strict: false };
|
|
957
|
+
function configureScheduler(store, canvasId, schedulerConfig, previous) {
|
|
958
|
+
const state = store.getState();
|
|
959
|
+
const scheduler = getScheduler();
|
|
960
|
+
const rootId = state.internal.rootId;
|
|
961
|
+
const ordersItself = schedulerConfig?.before !== void 0 || schedulerConfig?.after !== void 0;
|
|
962
|
+
const rootBefore = schedulerConfig?.before;
|
|
963
|
+
const rootAfter = ordersItself ? schedulerConfig?.after : state.internal.sharedAfter;
|
|
964
|
+
if (!rootId) {
|
|
965
|
+
const newRootId = state.internal.pendingRootId ?? canvasId ?? scheduler.generateRootId();
|
|
966
|
+
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
967
|
+
getState: () => store.getState(),
|
|
968
|
+
onError: (err) => store.getState().setError(err),
|
|
969
|
+
frameloop: store.getState().frameloop,
|
|
970
|
+
before: rootBefore,
|
|
971
|
+
after: rootAfter,
|
|
972
|
+
order: schedulerConfig?.order
|
|
973
|
+
});
|
|
974
|
+
const unregisterCanvasTarget = scheduler.register(
|
|
975
|
+
() => {
|
|
976
|
+
const state2 = store.getState();
|
|
977
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
978
|
+
if (canvasTarget) {
|
|
979
|
+
const renderer = state2.internal.actualRenderer;
|
|
980
|
+
if (renderer.getCanvasTarget() !== canvasTarget) renderer.setCanvasTarget(canvasTarget);
|
|
981
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
982
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
983
|
+
renderer.backend?.updateSize?.();
|
|
984
|
+
}
|
|
985
|
+
}
|
|
940
986
|
},
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
987
|
+
{
|
|
988
|
+
id: `${newRootId}_canvasTarget`,
|
|
989
|
+
rootId: newRootId,
|
|
990
|
+
phase: "start",
|
|
991
|
+
system: true
|
|
944
992
|
}
|
|
945
993
|
);
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
loadLoader(format).then((loader) => {
|
|
1027
|
-
useLoader.preload(loader, input, (loader2) => {
|
|
1028
|
-
loader2.setPath?.(path);
|
|
1029
|
-
if (extensions) extensions(loader2);
|
|
1030
|
-
});
|
|
1031
|
-
});
|
|
1032
|
-
};
|
|
1033
|
-
const clearDefaultOptins = {
|
|
1034
|
-
files: defaultFiles,
|
|
1035
|
-
preset: void 0
|
|
1036
|
-
};
|
|
1037
|
-
useEnvironment.clear = (clearOptions) => {
|
|
1038
|
-
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
1039
|
-
let { files } = options;
|
|
1040
|
-
const { preset } = options;
|
|
1041
|
-
if (preset) {
|
|
1042
|
-
validatePreset(preset);
|
|
1043
|
-
files = presetsObj[preset];
|
|
1044
|
-
}
|
|
1045
|
-
const { format } = getFormat(files);
|
|
1046
|
-
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1047
|
-
const input = isArray(files) ? [files] : files;
|
|
1048
|
-
const clear = (loader2) => useLoader.clear(loader2, input);
|
|
1049
|
-
const loader = loadedLoaders.get(format);
|
|
1050
|
-
if (loader) {
|
|
1051
|
-
clear(loader);
|
|
994
|
+
const unregisterEventsFlush = scheduler.register(
|
|
995
|
+
() => {
|
|
996
|
+
const state2 = store.getState();
|
|
997
|
+
state2.events.flush?.();
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
id: `${newRootId}_events`,
|
|
1001
|
+
rootId: newRootId,
|
|
1002
|
+
phase: "input",
|
|
1003
|
+
system: true
|
|
1004
|
+
}
|
|
1005
|
+
);
|
|
1006
|
+
const unregisterFrustum = scheduler.register(
|
|
1007
|
+
() => {
|
|
1008
|
+
const state2 = store.getState();
|
|
1009
|
+
if (state2.autoUpdateFrustum && state2.camera) {
|
|
1010
|
+
updateFrustum(state2.camera, state2.frustum);
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
id: `${newRootId}_frustum`,
|
|
1015
|
+
rootId: newRootId,
|
|
1016
|
+
before: "render",
|
|
1017
|
+
system: true
|
|
1018
|
+
}
|
|
1019
|
+
);
|
|
1020
|
+
const unregisterVisibility = scheduler.register(
|
|
1021
|
+
() => {
|
|
1022
|
+
const state2 = store.getState();
|
|
1023
|
+
checkVisibility(state2);
|
|
1024
|
+
},
|
|
1025
|
+
{
|
|
1026
|
+
id: `${newRootId}_visibility`,
|
|
1027
|
+
rootId: newRootId,
|
|
1028
|
+
before: "render",
|
|
1029
|
+
system: true,
|
|
1030
|
+
after: `${newRootId}_frustum`
|
|
1031
|
+
}
|
|
1032
|
+
);
|
|
1033
|
+
const unregisterRender = scheduler.register(
|
|
1034
|
+
() => {
|
|
1035
|
+
const state2 = store.getState();
|
|
1036
|
+
const renderer = state2.internal.actualRenderer;
|
|
1037
|
+
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
1038
|
+
if (userHandlesRender || state2.internal.priority) return;
|
|
1039
|
+
try {
|
|
1040
|
+
const renderOverride = state2.internal.renderOverride;
|
|
1041
|
+
if (renderOverride) renderOverride();
|
|
1042
|
+
else if (renderer?.render) renderer.render(state2.scene, state2.camera);
|
|
1043
|
+
} catch (error) {
|
|
1044
|
+
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
1045
|
+
}
|
|
1046
|
+
},
|
|
1047
|
+
{
|
|
1048
|
+
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
1049
|
+
id: canvasId || `${newRootId}_render`,
|
|
1050
|
+
rootId: newRootId,
|
|
1051
|
+
phase: "render",
|
|
1052
|
+
system: true,
|
|
1053
|
+
// Internal flag: this is a system job, not user-controlled
|
|
1054
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
1055
|
+
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
1056
|
+
}
|
|
1057
|
+
);
|
|
1058
|
+
state.set((state2) => ({
|
|
1059
|
+
internal: {
|
|
1060
|
+
...state2.internal,
|
|
1061
|
+
rootId: newRootId,
|
|
1062
|
+
pendingRootId: void 0,
|
|
1063
|
+
unregisterRoot: () => {
|
|
1064
|
+
unregisterRoot();
|
|
1065
|
+
unregisterCanvasTarget();
|
|
1066
|
+
unregisterEventsFlush();
|
|
1067
|
+
unregisterFrustum();
|
|
1068
|
+
unregisterVisibility();
|
|
1069
|
+
unregisterRender();
|
|
1070
|
+
},
|
|
1071
|
+
scheduler
|
|
1072
|
+
}
|
|
1073
|
+
}));
|
|
1052
1074
|
} else {
|
|
1053
|
-
const
|
|
1054
|
-
if (
|
|
1055
|
-
|
|
1075
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, previous?.before, shallowLoose$1) || !is.equ(schedulerConfig?.after, previous?.after, shallowLoose$1);
|
|
1076
|
+
if (constraintsChanged) {
|
|
1077
|
+
scheduler.setRootConstraints(rootId, {
|
|
1078
|
+
before: rootBefore,
|
|
1079
|
+
after: rootAfter
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
if (schedulerConfig?.order !== previous?.order) {
|
|
1083
|
+
scheduler.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
1084
|
+
}
|
|
1056
1085
|
}
|
|
1057
|
-
};
|
|
1058
|
-
function validatePreset(preset) {
|
|
1059
|
-
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
1060
|
-
}
|
|
1061
|
-
function getFormat(files) {
|
|
1062
|
-
const isCubemap = isArray(files) && files.length === 6;
|
|
1063
|
-
const firstEntry = isArray(files) ? files[0] : files;
|
|
1064
|
-
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1065
|
-
let format;
|
|
1066
|
-
if (isCubemap) format = firstExtension === "hdr" ? "hdr-cube" : "cube";
|
|
1067
|
-
else if (firstEntry.startsWith("data:application/exr")) format = "exr";
|
|
1068
|
-
else if (firstEntry.startsWith("data:application/hdr")) format = "hdr";
|
|
1069
|
-
else if (firstEntry.startsWith("data:image/jpeg")) format = "jpg";
|
|
1070
|
-
else if (firstExtension === "hdr" || firstExtension === "exr") format = firstExtension;
|
|
1071
|
-
else if (firstExtension === "jpg" || firstExtension === "jpeg") format = "jpg";
|
|
1072
|
-
return { format, isCubemap };
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
function useInstanceHandle(ref) {
|
|
1076
|
-
const instance = useRef(null);
|
|
1077
|
-
useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
1078
|
-
return instance;
|
|
1079
|
-
}
|
|
1080
|
-
function useGraph(object) {
|
|
1081
|
-
return useMemo(() => buildGraph(object), [object]);
|
|
1082
1086
|
}
|
|
1083
|
-
|
|
1084
1087
|
let effectId = 0;
|
|
1085
1088
|
function addEffect(callback) {
|
|
1086
1089
|
notifyDepreciated({
|
|
@@ -1121,22 +1124,815 @@ function advance(timestamp, runGlobalEffects, state) {
|
|
|
1121
1124
|
else scheduler.step(timestamp);
|
|
1122
1125
|
}
|
|
1123
1126
|
|
|
1124
|
-
const
|
|
1125
|
-
const
|
|
1126
|
-
|
|
1127
|
+
const isPromiseLike = (value) => typeof value?.then === "function";
|
|
1128
|
+
const fulfilled = (value) => Object.assign(Promise.resolve(value), { status: "fulfilled", value });
|
|
1129
|
+
const rejected = (reason) => {
|
|
1130
|
+
const promise = Promise.reject(reason);
|
|
1131
|
+
promise.catch(() => {
|
|
1132
|
+
});
|
|
1133
|
+
return Object.assign(promise, { status: "rejected", reason });
|
|
1134
|
+
};
|
|
1135
|
+
const deferred = () => {
|
|
1136
|
+
let resolve;
|
|
1137
|
+
let reject;
|
|
1138
|
+
const promise = new Promise((yes, no) => {
|
|
1139
|
+
resolve = (value) => {
|
|
1140
|
+
Object.assign(promise, { status: "fulfilled", value });
|
|
1141
|
+
yes(value);
|
|
1142
|
+
};
|
|
1143
|
+
reject = (reason) => {
|
|
1144
|
+
Object.assign(promise, { status: "rejected", reason });
|
|
1145
|
+
no(reason);
|
|
1146
|
+
};
|
|
1147
|
+
});
|
|
1148
|
+
promise.status = "pending";
|
|
1149
|
+
promise.catch(() => {
|
|
1150
|
+
});
|
|
1151
|
+
return { promise, resolve, reject };
|
|
1152
|
+
};
|
|
1153
|
+
function resolveThen(value, apply) {
|
|
1154
|
+
return isPromiseLike(value) ? Promise.resolve(value).then(apply) : apply(value);
|
|
1155
|
+
}
|
|
1127
1156
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1157
|
+
const isRenderer = (def) => !!def?.render;
|
|
1158
|
+
function ensureStoreThreeObjects(store) {
|
|
1159
|
+
const state = store.getState();
|
|
1160
|
+
if (state.pointer) return;
|
|
1161
|
+
const { Vector2, Frustum } = getThree();
|
|
1162
|
+
const pointer = new Vector2();
|
|
1163
|
+
state.set({ pointer, mouse: pointer, frustum: new Frustum() });
|
|
1130
1164
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1165
|
+
const R3F_RENDERER_SETTINGS = ["textureColorSpace", "shadows"];
|
|
1166
|
+
const NON_APPLIED_RENDERER_PROPS = /* @__PURE__ */ new Set([
|
|
1167
|
+
...R3F_RENDERER_SETTINGS,
|
|
1168
|
+
"canvas",
|
|
1169
|
+
"antialias",
|
|
1170
|
+
"alpha",
|
|
1171
|
+
"samples",
|
|
1172
|
+
"powerPreference",
|
|
1173
|
+
"depth",
|
|
1174
|
+
"stencil",
|
|
1175
|
+
"logarithmicDepthBuffer",
|
|
1176
|
+
"reversedDepthBuffer",
|
|
1177
|
+
// WebGPURenderer only
|
|
1178
|
+
"forceWebGL",
|
|
1179
|
+
"outputBufferType",
|
|
1180
|
+
"multiview",
|
|
1181
|
+
"getFallback",
|
|
1182
|
+
"trackTimestamp"
|
|
1183
|
+
]);
|
|
1184
|
+
function settingsBag(config) {
|
|
1185
|
+
return is.obj(config) && !isRenderer(config) ? config : void 0;
|
|
1186
|
+
}
|
|
1187
|
+
function isInstanceOrFactory(config) {
|
|
1188
|
+
return is.fun(config) || isRenderer(config);
|
|
1189
|
+
}
|
|
1190
|
+
function assertNoRemovedConfig(props) {
|
|
1191
|
+
if (props.primaryCanvas !== void 0) {
|
|
1192
|
+
throw new Error(
|
|
1193
|
+
'R3F: `primaryCanvas` was removed: mark the owner <Canvas primary> and other canvases share it automatically (or use share="id")'
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
if (props.shadows !== void 0) {
|
|
1197
|
+
throw new Error(
|
|
1198
|
+
"R3F: the `shadows` Canvas prop moved into the renderer settings: use `renderer={{ shadows }}` (or `gl={{ shadows }}` for WebGL and @react-three/fiber/legacy)"
|
|
1199
|
+
);
|
|
1200
|
+
}
|
|
1201
|
+
for (const name of ["renderer", "gl"]) {
|
|
1202
|
+
const bag = settingsBag(props[name]);
|
|
1203
|
+
if (!bag) continue;
|
|
1204
|
+
if ("primaryCanvas" in bag) {
|
|
1205
|
+
throw new Error(
|
|
1206
|
+
`R3F: \`${name}={{ primaryCanvas }}\` was removed: mark the owner <Canvas primary> and other canvases share it automatically (or use share="id")`
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
if ("scheduler" in bag) {
|
|
1210
|
+
throw new Error(`R3F: \`${name}={{ scheduler }}\` moved to <Canvas scheduler>`);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
function resolveRenderer(config, defaultProps, RendererClass) {
|
|
1215
|
+
if (typeof config === "function") {
|
|
1216
|
+
return resolveThen(config(defaultProps), (renderer) => ({
|
|
1217
|
+
renderer,
|
|
1218
|
+
owned: true
|
|
1219
|
+
}));
|
|
1220
|
+
}
|
|
1221
|
+
if (isRenderer(config)) return { renderer: config, owned: false };
|
|
1222
|
+
const params = { ...defaultProps };
|
|
1223
|
+
for (const key in settingsBag(config)) if (!R3F_RENDERER_SETTINGS.includes(key)) params[key] = config[key];
|
|
1224
|
+
return { renderer: new RendererClass(params), owned: true };
|
|
1225
|
+
}
|
|
1226
|
+
function createOwnedWebGPURenderer(rendererConfig, defaultGPUProps, canvas, propsSize, dpr, support) {
|
|
1227
|
+
return resolveThen(resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer), (resolved) => {
|
|
1228
|
+
const renderer = resolved.renderer;
|
|
1229
|
+
if (!renderer.hasInitialized?.()) {
|
|
1230
|
+
const size = computeInitialSize(canvas, propsSize);
|
|
1231
|
+
if (size.width > 0 && size.height > 0) {
|
|
1232
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
1233
|
+
renderer.setSize(size.width, size.height, false);
|
|
1234
|
+
}
|
|
1235
|
+
return resolveThen(renderer.init(), () => ({ renderer, owned: resolved.owned }));
|
|
1236
|
+
}
|
|
1237
|
+
return { renderer, owned: resolved.owned };
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
function initializeRenderer(canvas, provider, store, props) {
|
|
1241
|
+
const {
|
|
1242
|
+
id: canvasId,
|
|
1243
|
+
primary = false,
|
|
1244
|
+
share,
|
|
1245
|
+
gl: glConfig,
|
|
1246
|
+
renderer: rendererConfig,
|
|
1247
|
+
size: propsSize,
|
|
1248
|
+
dpr = [1, 2],
|
|
1249
|
+
_primaryToken
|
|
1250
|
+
} = props;
|
|
1251
|
+
assertNoRemovedConfig(props);
|
|
1252
|
+
const rendererBag = settingsBag(rendererConfig);
|
|
1253
|
+
const state = store.getState();
|
|
1254
|
+
const { webgl, webgpu } = provider;
|
|
1255
|
+
const defaultGLProps = {
|
|
1256
|
+
canvas,
|
|
1257
|
+
powerPreference: "high-performance",
|
|
1258
|
+
antialias: true,
|
|
1259
|
+
alpha: true
|
|
1260
|
+
};
|
|
1261
|
+
const defaultGPUProps = {
|
|
1262
|
+
canvas,
|
|
1263
|
+
antialias: true
|
|
1264
|
+
};
|
|
1265
|
+
if (glConfig && !webgl) {
|
|
1266
|
+
throw new Error(
|
|
1267
|
+
"WebGLRenderer (gl prop) is not available on this entry. Use @react-three/fiber or @react-three/fiber/legacy instead."
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
if (rendererConfig && !webgpu) {
|
|
1271
|
+
throw new Error(
|
|
1272
|
+
"WebGPURenderer (renderer prop) is not available on this entry. Use @react-three/fiber or @react-three/fiber/webgpu instead."
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
if (glConfig && rendererConfig) {
|
|
1276
|
+
throw new Error("Cannot use both gl and renderer props at the same time");
|
|
1277
|
+
}
|
|
1278
|
+
if (primary && !webgpu) {
|
|
1279
|
+
throw new Error(
|
|
1280
|
+
"R3F: <Canvas primary> shares a WebGPU renderer and is not available on this entry. Use @react-three/fiber or @react-three/fiber/webgpu instead."
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
if (primary && glConfig) {
|
|
1284
|
+
throw new Error(
|
|
1285
|
+
"R3F: <Canvas primary> shares a WebGPU renderer and cannot be used with WebGL. Remove the `gl` prop or use the `renderer` prop."
|
|
1286
|
+
);
|
|
1287
|
+
}
|
|
1288
|
+
if (primary && is.str(share)) {
|
|
1289
|
+
throw new Error(`R3F: a <Canvas primary> owns its renderer; remove share="${share}" from it.`);
|
|
1290
|
+
}
|
|
1291
|
+
if (is.str(share)) {
|
|
1292
|
+
if (!webgpu || glConfig) {
|
|
1293
|
+
throw new Error(
|
|
1294
|
+
`R3F: share="${share}" borrows a WebGPU renderer and cannot be used with WebGL. Remove the \`gl\` prop, or use @react-three/fiber or @react-three/fiber/webgpu.`
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
if (isInstanceOrFactory(rendererConfig)) {
|
|
1298
|
+
throw new Error(
|
|
1299
|
+
`R3F: share="${share}" borrows the primary's renderer, so it cannot be combined with a renderer instance or factory. Remove one of the two.`
|
|
1300
|
+
);
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
const primaryKey = canvasId || DEFAULT_PRIMARY;
|
|
1304
|
+
const primaryToken = _primaryToken ?? store;
|
|
1305
|
+
if (primary && !state.internal.actualRenderer) {
|
|
1306
|
+
announcePrimary(primaryKey, primaryToken);
|
|
1307
|
+
state.internal.unregisterPrimary = () => withdrawPrimary(primaryKey, primaryToken);
|
|
1308
|
+
if (primaryConflict(primaryKey, primaryToken)) {
|
|
1309
|
+
throw new Error(
|
|
1310
|
+
primaryKey === DEFAULT_PRIMARY ? 'R3F: two <Canvas primary> are mounted without ids. Give each primary a distinct `id`, and point the other canvases at one with share="id".' : `R3F: two <Canvas primary> use the id "${primaryKey}". Give each primary a distinct \`id\`.`
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
let shareKey;
|
|
1315
|
+
if (!state.internal.actualRenderer && webgpu && !primary && !glConfig && !state.isLegacy) {
|
|
1316
|
+
if (is.str(share)) {
|
|
1317
|
+
shareKey = share;
|
|
1318
|
+
} else if (share !== false && !isInstanceOrFactory(rendererConfig)) {
|
|
1319
|
+
const live = livePrimaryKeys();
|
|
1320
|
+
if (live.length > 1) {
|
|
1321
|
+
throw new Error(
|
|
1322
|
+
`R3F: ${live.length} primaries are mounted (${live.map(describePrimary).join(", ")}), so this canvas cannot pick one to share. Pass share="id" to name one, or share={false} for its own renderer.`
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
shareKey = live[0];
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
const explicitShare = is.str(share);
|
|
1329
|
+
const wantsGL = !!webgl && (state.isLegacy || !!glConfig || !webgpu || !rendererConfig && !primary && shareKey === void 0);
|
|
1330
|
+
if (webgl && webgpu && !state.isLegacy && wantsGL) {
|
|
1331
|
+
notifyDepreciated({
|
|
1332
|
+
heading: "WebGlRenderer Usage",
|
|
1333
|
+
body: "WebGlRenderer usage is deprecated in favor of WebGPU. Import from /legacy directly or upgrade to WebGPU.",
|
|
1334
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/renderer"
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
let renderer = state.internal.actualRenderer;
|
|
1338
|
+
if (!state.internal.actualRenderer) {
|
|
1339
|
+
return resolveThen(wantsGL ? webgl() : webgpu(), (support) => {
|
|
1340
|
+
registerThree(support.three);
|
|
1341
|
+
state.internal.support = support;
|
|
1342
|
+
ensureStoreThreeObjects(store);
|
|
1343
|
+
if (support.kind === "webgl") {
|
|
1344
|
+
return resolveThen(resolveRenderer(glConfig, defaultGLProps, support.Renderer), (resolved) => {
|
|
1345
|
+
renderer = resolved.renderer;
|
|
1346
|
+
state.internal.actualRenderer = renderer;
|
|
1347
|
+
state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
|
|
1348
|
+
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
const primaryReady = shareKey === void 0 ? null : explicitShare ? waitForPrimary(shareKey) : waitForAnnouncedPrimary(shareKey);
|
|
1352
|
+
return resolveThen(primaryReady, (primaryEntry) => {
|
|
1353
|
+
if (primaryEntry && primaryEntry.store.getState().webGPUSupported) {
|
|
1354
|
+
renderer = primaryEntry.renderer;
|
|
1355
|
+
state.internal.actualRenderer = renderer;
|
|
1356
|
+
state.internal.releaseRenderer = borrowRenderer(renderer);
|
|
1357
|
+
state.internal.sharedAfter = primaryEntry.rootId;
|
|
1358
|
+
const canvasTarget = new support.CanvasTarget(canvas);
|
|
1359
|
+
primaryEntry.store.setState((prev) => ({
|
|
1360
|
+
internal: { ...prev.internal, isMultiCanvas: true }
|
|
1361
|
+
}));
|
|
1362
|
+
state.set((prev) => ({
|
|
1363
|
+
webGPUSupported: primaryEntry.store.getState().webGPUSupported,
|
|
1364
|
+
renderer,
|
|
1365
|
+
primaryStore: primaryEntry.store,
|
|
1366
|
+
internal: {
|
|
1367
|
+
...prev.internal,
|
|
1368
|
+
canvasTarget,
|
|
1369
|
+
isMultiCanvas: true,
|
|
1370
|
+
isSecondary: true,
|
|
1371
|
+
targetId: shareKey === DEFAULT_PRIMARY ? void 0 : shareKey
|
|
1372
|
+
}
|
|
1373
|
+
}));
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
if (primaryEntry) {
|
|
1377
|
+
return resolveThen(
|
|
1378
|
+
createOwnedWebGPURenderer(
|
|
1379
|
+
{ ...rendererBag, forceWebGL: true },
|
|
1380
|
+
defaultGPUProps,
|
|
1381
|
+
canvas,
|
|
1382
|
+
propsSize,
|
|
1383
|
+
dpr,
|
|
1384
|
+
support
|
|
1385
|
+
),
|
|
1386
|
+
(resolved) => {
|
|
1387
|
+
renderer = resolved.renderer;
|
|
1388
|
+
const backend = renderer.backend;
|
|
1389
|
+
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
1390
|
+
state.internal.actualRenderer = renderer;
|
|
1391
|
+
state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
|
|
1392
|
+
state.set((prev) => ({
|
|
1393
|
+
webGPUSupported: isWebGPUBackend,
|
|
1394
|
+
renderer,
|
|
1395
|
+
primaryStore: store,
|
|
1396
|
+
internal: {
|
|
1397
|
+
...prev.internal,
|
|
1398
|
+
canvasTarget: renderer.getCanvasTarget?.(),
|
|
1399
|
+
sharedRendererFallback: true
|
|
1400
|
+
}
|
|
1401
|
+
}));
|
|
1402
|
+
}
|
|
1403
|
+
);
|
|
1404
|
+
}
|
|
1405
|
+
return resolveThen(
|
|
1406
|
+
createOwnedWebGPURenderer(rendererConfig, defaultGPUProps, canvas, propsSize, dpr, support),
|
|
1407
|
+
(resolved) => {
|
|
1408
|
+
var _a;
|
|
1409
|
+
renderer = resolved.renderer;
|
|
1410
|
+
const backend = renderer.backend;
|
|
1411
|
+
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
1412
|
+
state.internal.actualRenderer = renderer;
|
|
1413
|
+
state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
|
|
1414
|
+
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
1415
|
+
if (primary) {
|
|
1416
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
1417
|
+
(_a = state.internal).pendingRootId ?? (_a.pendingRootId = canvasId || getScheduler().generateRootId());
|
|
1418
|
+
registerPrimary(primaryKey, renderer, store, {
|
|
1419
|
+
token: primaryToken,
|
|
1420
|
+
rootId: state.internal.pendingRootId
|
|
1421
|
+
});
|
|
1422
|
+
state.set((prev) => ({ internal: { ...prev.internal, canvasTarget } }));
|
|
1423
|
+
} else if (share !== false && !isInstanceOrFactory(rendererConfig)) {
|
|
1424
|
+
state.internal.untrackStandalone = trackStandalone(store);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
);
|
|
1428
|
+
});
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
const records = /* @__PURE__ */ new WeakMap();
|
|
1433
|
+
function take(renderer, record) {
|
|
1434
|
+
record.leases++;
|
|
1435
|
+
let released = false;
|
|
1436
|
+
return () => {
|
|
1437
|
+
if (released) return;
|
|
1438
|
+
released = true;
|
|
1439
|
+
if (--record.leases > 0) return;
|
|
1440
|
+
records.delete(renderer);
|
|
1441
|
+
if (record.owned) return disposeRenderer(renderer);
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
function leaseRenderer(renderer, owned) {
|
|
1445
|
+
let record = records.get(renderer);
|
|
1446
|
+
if (!record) records.set(renderer, record = { owned, leases: 0 });
|
|
1447
|
+
return take(renderer, record);
|
|
1448
|
+
}
|
|
1449
|
+
function borrowRenderer(renderer) {
|
|
1450
|
+
const record = records.get(renderer);
|
|
1451
|
+
if (!record) throw new Error("R3F: cannot share a renderer whose canvas has already unmounted");
|
|
1452
|
+
return take(renderer, record);
|
|
1453
|
+
}
|
|
1454
|
+
function disposeRenderer(renderer) {
|
|
1455
|
+
if (renderer.hasInitialized?.() === false) return;
|
|
1456
|
+
const warn = (error) => console.warn("[R3F] Error disposing renderer", error);
|
|
1457
|
+
const loseContext = () => {
|
|
1458
|
+
try {
|
|
1459
|
+
;
|
|
1460
|
+
renderer.forceContextLoss?.();
|
|
1461
|
+
} catch (error) {
|
|
1462
|
+
warn(error);
|
|
1463
|
+
}
|
|
1464
|
+
};
|
|
1465
|
+
let disposed;
|
|
1466
|
+
try {
|
|
1467
|
+
disposed = renderer.dispose ? renderer.dispose() : renderer.renderLists?.dispose?.();
|
|
1468
|
+
} catch (error) {
|
|
1469
|
+
warn(error);
|
|
1470
|
+
}
|
|
1471
|
+
if (typeof disposed?.then === "function") {
|
|
1472
|
+
return Promise.resolve(disposed).then(loseContext, (error) => {
|
|
1473
|
+
warn(error);
|
|
1474
|
+
loseContext();
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
loseContext();
|
|
1478
|
+
}
|
|
1479
|
+
const DEFAULT_PRIMARY = "\0r3f:primary";
|
|
1480
|
+
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
1481
|
+
const announcements = /* @__PURE__ */ new Map();
|
|
1482
|
+
const withdrawing = /* @__PURE__ */ new Set();
|
|
1483
|
+
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
1484
|
+
const standaloneRoots = /* @__PURE__ */ new Set();
|
|
1485
|
+
const warnedLatePrimary = /* @__PURE__ */ new WeakSet();
|
|
1486
|
+
function describePrimary(key) {
|
|
1487
|
+
return key === DEFAULT_PRIMARY ? "<Canvas primary>" : `<Canvas id="${key}" primary>`;
|
|
1488
|
+
}
|
|
1489
|
+
function notify(key, entry) {
|
|
1490
|
+
const subscribers = pendingSubscribers.get(key);
|
|
1491
|
+
if (!subscribers) return;
|
|
1492
|
+
pendingSubscribers.delete(key);
|
|
1493
|
+
subscribers.forEach((callback) => callback(entry));
|
|
1494
|
+
}
|
|
1495
|
+
function isLive(key) {
|
|
1496
|
+
const owners = announcements.get(key);
|
|
1497
|
+
if (owners) {
|
|
1498
|
+
for (const owner of owners) if (!withdrawing.has(owner)) return true;
|
|
1499
|
+
}
|
|
1500
|
+
const entry = primaryRegistry.get(key);
|
|
1501
|
+
return !!entry && !(entry.token && withdrawing.has(entry.token));
|
|
1502
|
+
}
|
|
1503
|
+
function announcePrimary(key, owner) {
|
|
1504
|
+
withdrawing.delete(owner);
|
|
1505
|
+
let owners = announcements.get(key);
|
|
1506
|
+
if (!owners) announcements.set(key, owners = /* @__PURE__ */ new Set());
|
|
1507
|
+
if (owners.has(owner)) return;
|
|
1508
|
+
owners.add(owner);
|
|
1509
|
+
if (standaloneRoots.size > 0 && !warnedLatePrimary.has(owner) && isDevelopment()) {
|
|
1510
|
+
warnedLatePrimary.add(owner);
|
|
1511
|
+
console.warn(
|
|
1512
|
+
`R3F: ${describePrimary(key)} mounted after ${standaloneRoots.size} other WebGPU canvas(es) had already created their own renderer; those keep it and do not share the primary. Mount the primary with or before the canvases that share it, or give them share="id" so they wait for it.`
|
|
1513
|
+
);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
function markWithdrawing(owner) {
|
|
1517
|
+
withdrawing.add(owner);
|
|
1518
|
+
}
|
|
1519
|
+
function withdrawPrimary(key, owner) {
|
|
1520
|
+
withdrawing.delete(owner);
|
|
1521
|
+
const owners = announcements.get(key);
|
|
1522
|
+
if (owners) {
|
|
1523
|
+
owners.delete(owner);
|
|
1524
|
+
if (owners.size === 0) announcements.delete(key);
|
|
1525
|
+
}
|
|
1526
|
+
const entry = primaryRegistry.get(key);
|
|
1527
|
+
if (entry?.token === owner) primaryRegistry.delete(key);
|
|
1528
|
+
if (!isLive(key)) notify(key, null);
|
|
1529
|
+
}
|
|
1530
|
+
function primaryConflict(key, owner) {
|
|
1531
|
+
const owners = announcements.get(key);
|
|
1532
|
+
if (owners) {
|
|
1533
|
+
for (const other of owners) {
|
|
1534
|
+
if (other === owner) break;
|
|
1535
|
+
if (!withdrawing.has(other)) return true;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
const entry = primaryRegistry.get(key);
|
|
1539
|
+
return !!entry && entry.token !== owner && !(entry.token && withdrawing.has(entry.token));
|
|
1540
|
+
}
|
|
1541
|
+
function livePrimaryKeys() {
|
|
1542
|
+
const keys = /* @__PURE__ */ new Set([...announcements.keys(), ...primaryRegistry.keys()]);
|
|
1543
|
+
return [...keys].filter(isLive);
|
|
1544
|
+
}
|
|
1545
|
+
function trackStandalone(owner) {
|
|
1546
|
+
standaloneRoots.add(owner);
|
|
1547
|
+
return () => {
|
|
1548
|
+
standaloneRoots.delete(owner);
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
function registerPrimary(id, renderer, store, options = {}) {
|
|
1552
|
+
if (options.token && !announcements.get(id)?.has(options.token)) return () => {
|
|
1553
|
+
};
|
|
1554
|
+
if (primaryRegistry.has(id)) {
|
|
1555
|
+
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
1556
|
+
}
|
|
1557
|
+
const entry = { renderer, store, rootId: options.rootId, token: options.token };
|
|
1558
|
+
primaryRegistry.set(id, entry);
|
|
1559
|
+
notify(id, entry);
|
|
1560
|
+
return () => {
|
|
1561
|
+
const currentEntry = primaryRegistry.get(id);
|
|
1562
|
+
if (currentEntry?.renderer === renderer) {
|
|
1563
|
+
primaryRegistry.delete(id);
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
function getPrimary(id) {
|
|
1568
|
+
return primaryRegistry.get(id);
|
|
1569
|
+
}
|
|
1570
|
+
function subscribe(id, callback) {
|
|
1571
|
+
if (!pendingSubscribers.has(id)) pendingSubscribers.set(id, []);
|
|
1572
|
+
pendingSubscribers.get(id).push(callback);
|
|
1573
|
+
return () => {
|
|
1574
|
+
const subscribers = pendingSubscribers.get(id);
|
|
1575
|
+
if (!subscribers) return;
|
|
1576
|
+
const index = subscribers.indexOf(callback);
|
|
1577
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
1578
|
+
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
1581
|
+
function waitForPrimary(id, timeout = 5e3) {
|
|
1582
|
+
const existing = primaryRegistry.get(id);
|
|
1583
|
+
if (existing) {
|
|
1584
|
+
return Promise.resolve(existing);
|
|
1585
|
+
}
|
|
1586
|
+
return new Promise((resolve, reject) => {
|
|
1587
|
+
let unsubscribe = () => {
|
|
1588
|
+
};
|
|
1589
|
+
const timeoutId = setTimeout(() => {
|
|
1590
|
+
unsubscribe();
|
|
1591
|
+
reject(
|
|
1592
|
+
new Error(
|
|
1593
|
+
`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}" primary> is mounted for share="${id}".`
|
|
1594
|
+
)
|
|
1595
|
+
);
|
|
1596
|
+
}, timeout);
|
|
1597
|
+
const callback = (entry) => {
|
|
1598
|
+
if (!entry) {
|
|
1599
|
+
unsubscribe = subscribe(id, callback);
|
|
1600
|
+
return;
|
|
1601
|
+
}
|
|
1602
|
+
clearTimeout(timeoutId);
|
|
1603
|
+
resolve(entry);
|
|
1604
|
+
};
|
|
1605
|
+
unsubscribe = subscribe(id, callback);
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
function waitForAnnouncedPrimary(key, timeout = 5e3) {
|
|
1609
|
+
const existing = primaryRegistry.get(key);
|
|
1610
|
+
if (existing && isLive(key)) return Promise.resolve(existing);
|
|
1611
|
+
if (!isLive(key)) return Promise.resolve(null);
|
|
1612
|
+
return new Promise((resolve, reject) => {
|
|
1613
|
+
const timeoutId = setTimeout(() => {
|
|
1614
|
+
unsubscribe();
|
|
1615
|
+
reject(
|
|
1616
|
+
new Error(
|
|
1617
|
+
`Timeout waiting for ${describePrimary(key)} to create its renderer. A canvas mounted next to it shares its renderer automatically; pass share={false} to give it its own.`
|
|
1618
|
+
)
|
|
1619
|
+
);
|
|
1620
|
+
}, timeout);
|
|
1621
|
+
const unsubscribe = subscribe(key, (entry) => {
|
|
1622
|
+
clearTimeout(timeoutId);
|
|
1623
|
+
resolve(entry);
|
|
1624
|
+
});
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
function hasPrimary(id) {
|
|
1628
|
+
return primaryRegistry.has(id);
|
|
1629
|
+
}
|
|
1630
|
+
function unregisterPrimary(id) {
|
|
1631
|
+
primaryRegistry.delete(id);
|
|
1632
|
+
}
|
|
1633
|
+
function getPrimaryIds() {
|
|
1634
|
+
return Array.from(primaryRegistry.keys());
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
const shallowLoose = { objects: "shallow", strict: false };
|
|
1638
|
+
function watchDpr(onChange) {
|
|
1639
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function" || !window.devicePixelRatio) {
|
|
1640
|
+
return () => {
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
let watching = true;
|
|
1644
|
+
let query;
|
|
1645
|
+
const listen = () => {
|
|
1646
|
+
try {
|
|
1647
|
+
query = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
1648
|
+
if (typeof query?.addEventListener === "function") query.addEventListener("change", handleChange);
|
|
1649
|
+
else query?.addListener?.(handleChange);
|
|
1650
|
+
} catch {
|
|
1651
|
+
query = void 0;
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
const unlisten = () => {
|
|
1655
|
+
if (typeof query?.removeEventListener === "function") query.removeEventListener("change", handleChange);
|
|
1656
|
+
else query?.removeListener?.(handleChange);
|
|
1657
|
+
query = void 0;
|
|
1658
|
+
};
|
|
1659
|
+
const handleChange = () => {
|
|
1660
|
+
if (!watching) return;
|
|
1661
|
+
unlisten();
|
|
1662
|
+
listen();
|
|
1663
|
+
onChange();
|
|
1664
|
+
};
|
|
1665
|
+
listen();
|
|
1666
|
+
return () => {
|
|
1667
|
+
watching = false;
|
|
1668
|
+
unlisten();
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
function createRootConfiguration(store, canvas) {
|
|
1672
|
+
let previous;
|
|
1673
|
+
let lastCamera;
|
|
1674
|
+
const lastConfiguredProps = {};
|
|
1675
|
+
let resolvedDpr = 0;
|
|
1676
|
+
let dprChangedInXR = false;
|
|
1677
|
+
let unwatchDpr;
|
|
1678
|
+
const resolveDpr = () => {
|
|
1679
|
+
const state = store.getState();
|
|
1680
|
+
const xr = state.internal.actualRenderer?.xr;
|
|
1681
|
+
if (xr?.isPresenting || xr?.getSession?.()) {
|
|
1682
|
+
dprChangedInXR = true;
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
dprChangedInXR = false;
|
|
1686
|
+
const dpr = lastConfiguredProps.dpr;
|
|
1687
|
+
if (dpr === void 0 || state.viewport.dpr !== resolvedDpr || calculateDpr(dpr) === resolvedDpr) return;
|
|
1688
|
+
state.setDpr(dpr);
|
|
1689
|
+
resolvedDpr = store.getState().viewport.dpr;
|
|
1690
|
+
};
|
|
1691
|
+
let warnedSharedSettings = false;
|
|
1692
|
+
let configured = false;
|
|
1693
|
+
return (props) => {
|
|
1694
|
+
const {
|
|
1695
|
+
gl: glConfig,
|
|
1696
|
+
renderer: rendererConfig,
|
|
1697
|
+
size: propsSize,
|
|
1698
|
+
scene: sceneOptions,
|
|
1699
|
+
events,
|
|
1700
|
+
orthographic = false,
|
|
1701
|
+
frameloop = "always",
|
|
1702
|
+
dpr = [1, 2],
|
|
1703
|
+
performance,
|
|
1704
|
+
raycaster: raycastOptions,
|
|
1705
|
+
camera: cameraOptions,
|
|
1706
|
+
onPointerMissed,
|
|
1707
|
+
onDragOverMissed,
|
|
1708
|
+
onDropMissed,
|
|
1709
|
+
autoUpdateFrustum = true,
|
|
1710
|
+
occlusion = false,
|
|
1711
|
+
_sizeProps,
|
|
1712
|
+
forceEven
|
|
1713
|
+
} = props;
|
|
1714
|
+
assertNoRemovedConfig(props);
|
|
1715
|
+
const rendererBag = settingsBag(rendererConfig);
|
|
1716
|
+
const settings = settingsBag(glConfig) ?? rendererBag;
|
|
1717
|
+
const requestedTextureColorSpace = settings?.textureColorSpace || void 0;
|
|
1718
|
+
const shadows = isInstanceOrFactory(glConfig ?? rendererConfig) ? void 0 : settings?.shadows ?? false;
|
|
1719
|
+
const next = { ...props, shadows, frameloop, autoUpdateFrustum, occlusion };
|
|
1720
|
+
const last = previous;
|
|
1721
|
+
const changed = (key) => !last || !is.equ(next[key], last[key], { objects: "shallow" });
|
|
1722
|
+
previous = void 0;
|
|
1723
|
+
const state = store.getState();
|
|
1724
|
+
const renderer = state.internal.actualRenderer;
|
|
1725
|
+
const three = getThree();
|
|
1726
|
+
const borrowsRenderer = state.internal.isSecondary === true;
|
|
1727
|
+
if (borrowsRenderer && !warnedSharedSettings && rendererBag && Object.keys(rendererBag).some((key) => key !== "textureColorSpace") && isDevelopment()) {
|
|
1728
|
+
warnedSharedSettings = true;
|
|
1729
|
+
console.warn(
|
|
1730
|
+
"R3F: renderer settings on a sharing canvas are ignored; set them on the <Canvas primary>. This canvas borrows the primary's renderer, so renderer-wide settings come from the primary. Pass share={false} to give this canvas its own renderer."
|
|
1731
|
+
);
|
|
1732
|
+
}
|
|
1733
|
+
let raycaster = state.raycaster;
|
|
1734
|
+
if (!raycaster) state.set({ raycaster: raycaster = new three.Raycaster() });
|
|
1735
|
+
if (changed("raycaster")) {
|
|
1736
|
+
const { params, ...options } = raycastOptions || {};
|
|
1737
|
+
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options });
|
|
1738
|
+
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
1739
|
+
applyProps(raycaster, { params: { ...raycaster.params, ...params } });
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
let tempCamera = state.camera;
|
|
1743
|
+
if (!state.camera || state.camera === lastCamera && changed("camera")) {
|
|
1744
|
+
lastCamera = cameraOptions;
|
|
1745
|
+
const isCamera = cameraOptions?.isCamera;
|
|
1746
|
+
const camera = isCamera ? cameraOptions : orthographic ? new three.OrthographicCamera(0, 0, 0, 0, 0.1, 1e3) : new three.PerspectiveCamera(50, 0, 0.1, 1e3);
|
|
1747
|
+
if (!isCamera) {
|
|
1748
|
+
camera.position.z = 5;
|
|
1749
|
+
if (cameraOptions) {
|
|
1750
|
+
applyProps(camera, cameraOptions);
|
|
1751
|
+
if (!camera.manual) {
|
|
1752
|
+
const projectionProps = ["aspect", "left", "right", "bottom", "top"];
|
|
1753
|
+
if (projectionProps.some((prop) => prop in cameraOptions)) {
|
|
1754
|
+
camera.manual = true;
|
|
1755
|
+
camera.updateProjectionMatrix();
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
if (!state.camera && !cameraOptions?.rotation) camera.lookAt(0, 0, 0);
|
|
1760
|
+
}
|
|
1761
|
+
state.set({ camera });
|
|
1762
|
+
tempCamera = camera;
|
|
1763
|
+
raycaster.camera = camera;
|
|
1764
|
+
}
|
|
1765
|
+
if (!state.scene) {
|
|
1766
|
+
let scene;
|
|
1767
|
+
if (sceneOptions?.isScene) {
|
|
1768
|
+
scene = sceneOptions;
|
|
1769
|
+
prepare(scene, store, "", {});
|
|
1770
|
+
} else {
|
|
1771
|
+
scene = new three.Scene();
|
|
1772
|
+
prepare(scene, store, "", {});
|
|
1773
|
+
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
1774
|
+
}
|
|
1775
|
+
state.set((prev) => ({
|
|
1776
|
+
scene,
|
|
1777
|
+
rootScene: scene,
|
|
1778
|
+
internal: { ...prev.internal, container: scene }
|
|
1779
|
+
}));
|
|
1780
|
+
const camera = tempCamera;
|
|
1781
|
+
if (camera && !camera.parent) scene.add(camera);
|
|
1782
|
+
}
|
|
1783
|
+
if (events && !state.events.handlers) {
|
|
1784
|
+
state.set({ events: events(store) });
|
|
1785
|
+
let wasEnabled = true;
|
|
1786
|
+
store.subscribe((state2) => {
|
|
1787
|
+
const { enabled } = state2.events;
|
|
1788
|
+
if (enabled && !wasEnabled) {
|
|
1789
|
+
state2.events.update?.();
|
|
1790
|
+
}
|
|
1791
|
+
wasEnabled = enabled;
|
|
1792
|
+
});
|
|
1793
|
+
}
|
|
1794
|
+
if (_sizeProps !== void 0 && changed("_sizeProps")) {
|
|
1795
|
+
state.set({ _sizeProps });
|
|
1796
|
+
}
|
|
1797
|
+
if (forceEven !== void 0 && state.internal.forceEven !== forceEven) {
|
|
1798
|
+
state.set((prev) => ({ internal: { ...prev.internal, forceEven } }));
|
|
1799
|
+
}
|
|
1800
|
+
configureSize(store, computeInitialSize(canvas, propsSize));
|
|
1801
|
+
if (dpr !== void 0 && (!last || !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose))) {
|
|
1802
|
+
state.setDpr(dpr);
|
|
1803
|
+
lastConfiguredProps.dpr = dpr;
|
|
1804
|
+
resolvedDpr = store.getState().viewport.dpr;
|
|
1805
|
+
}
|
|
1806
|
+
const internal = store.getState().internal;
|
|
1807
|
+
if (Array.isArray(dpr) && (!unwatchDpr || internal.unwatchDpr !== unwatchDpr)) {
|
|
1808
|
+
internal.unwatchDpr?.();
|
|
1809
|
+
internal.unwatchDpr = unwatchDpr = watchDpr(resolveDpr);
|
|
1810
|
+
}
|
|
1811
|
+
resolveDpr();
|
|
1812
|
+
if (frameloop !== void 0 && changed("frameloop")) {
|
|
1813
|
+
state.setFrameloop(frameloop);
|
|
1814
|
+
}
|
|
1815
|
+
if (changed("onPointerMissed")) state.set({ onPointerMissed });
|
|
1816
|
+
if (changed("onDragOverMissed")) state.set({ onDragOverMissed });
|
|
1817
|
+
if (changed("onDropMissed")) state.set({ onDropMissed });
|
|
1818
|
+
if (changed("autoUpdateFrustum") && state.autoUpdateFrustum !== autoUpdateFrustum) {
|
|
1819
|
+
state.set({ autoUpdateFrustum });
|
|
1820
|
+
}
|
|
1821
|
+
if (occlusion && !state.internal.occlusionEnabled) {
|
|
1822
|
+
enableOcclusion(store);
|
|
1823
|
+
}
|
|
1824
|
+
if (performance && changed("performance")) {
|
|
1825
|
+
state.set((state2) => ({ performance: { ...state2.performance, ...performance } }));
|
|
1826
|
+
}
|
|
1827
|
+
if (!state.xr) {
|
|
1828
|
+
const handleXRFrame = (timestamp, _frame) => {
|
|
1829
|
+
const state2 = store.getState();
|
|
1830
|
+
if (state2.frameloop === "never") return;
|
|
1831
|
+
advance(timestamp, true, state2);
|
|
1832
|
+
};
|
|
1833
|
+
const actualRenderer = state.internal.actualRenderer;
|
|
1834
|
+
const handleSessionChange = () => {
|
|
1835
|
+
const state2 = store.getState();
|
|
1836
|
+
const renderer2 = state2.internal.actualRenderer;
|
|
1837
|
+
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
1838
|
+
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
1839
|
+
if (!renderer2.xr.isPresenting) {
|
|
1840
|
+
if (dprChangedInXR) resolveDpr();
|
|
1841
|
+
invalidate(state2);
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1844
|
+
const xr = {
|
|
1845
|
+
connect() {
|
|
1846
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
1847
|
+
const xrManager = (renderer2 || gl).xr;
|
|
1848
|
+
xrManager.addEventListener("sessionstart", handleSessionChange);
|
|
1849
|
+
xrManager.addEventListener("sessionend", handleSessionChange);
|
|
1850
|
+
},
|
|
1851
|
+
disconnect() {
|
|
1852
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
1853
|
+
const xrManager = (renderer2 || gl).xr;
|
|
1854
|
+
xrManager.removeEventListener("sessionstart", handleSessionChange);
|
|
1855
|
+
xrManager.removeEventListener("sessionend", handleSessionChange);
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
if (!borrowsRenderer && typeof renderer.xr?.addEventListener === "function") xr.connect();
|
|
1859
|
+
state.set({ xr });
|
|
1860
|
+
}
|
|
1861
|
+
if (!borrowsRenderer && shadows !== void 0 && renderer.shadowMap && changed("shadows")) {
|
|
1862
|
+
const oldEnabled = renderer.shadowMap.enabled;
|
|
1863
|
+
const oldType = renderer.shadowMap.type;
|
|
1864
|
+
renderer.shadowMap.enabled = !!shadows;
|
|
1865
|
+
if (is.boo(shadows)) {
|
|
1866
|
+
renderer.shadowMap.type = three.PCFShadowMap;
|
|
1867
|
+
} else if (is.str(shadows)) {
|
|
1868
|
+
if (shadows === "soft") {
|
|
1869
|
+
notifyDepreciated({
|
|
1870
|
+
heading: 'shadows="soft" is deprecated',
|
|
1871
|
+
body: "Three has depreciated soft and improved basic PCFShadows, we converted for you.",
|
|
1872
|
+
link: "https://github.com/mrdoob/three.js/wiki/Migration-Guide?utm_source=chatgpt.com#181--182"
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
const types = {
|
|
1876
|
+
basic: three.BasicShadowMap,
|
|
1877
|
+
percentage: three.PCFShadowMap,
|
|
1878
|
+
soft: three.PCFShadowMap,
|
|
1879
|
+
variance: three.VSMShadowMap
|
|
1880
|
+
};
|
|
1881
|
+
renderer.shadowMap.type = types[shadows] ?? three.PCFShadowMap;
|
|
1882
|
+
} else if (is.obj(shadows)) {
|
|
1883
|
+
Object.assign(renderer.shadowMap, shadows);
|
|
1884
|
+
}
|
|
1885
|
+
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
1886
|
+
renderer.shadowMap.needsUpdate = true;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
if (!configured && !borrowsRenderer) {
|
|
1890
|
+
renderer.outputColorSpace = three.SRGBColorSpace;
|
|
1891
|
+
renderer.toneMapping = three.ACESFilmicToneMapping;
|
|
1892
|
+
}
|
|
1893
|
+
const textureColorSpace = requestedTextureColorSpace ?? three.SRGBColorSpace;
|
|
1894
|
+
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
1895
|
+
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
1896
|
+
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
1897
|
+
}
|
|
1898
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && changed("gl")) {
|
|
1899
|
+
const glProps = {};
|
|
1900
|
+
for (const key in glConfig) {
|
|
1901
|
+
if (!NON_APPLIED_RENDERER_PROPS.has(key)) glProps[key] = glConfig[key];
|
|
1902
|
+
}
|
|
1903
|
+
applyProps(renderer, glProps);
|
|
1904
|
+
}
|
|
1905
|
+
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer && !borrowsRenderer) {
|
|
1906
|
+
const currentRenderer = state.renderer;
|
|
1907
|
+
if (changed("renderer")) {
|
|
1908
|
+
const rendererProps = {};
|
|
1909
|
+
for (const key in rendererConfig) {
|
|
1910
|
+
if (!NON_APPLIED_RENDERER_PROPS.has(key)) rendererProps[key] = rendererConfig[key];
|
|
1911
|
+
}
|
|
1912
|
+
applyProps(currentRenderer, rendererProps);
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
configured = true;
|
|
1916
|
+
previous = next;
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
const version = "10.0.0-alpha.5";
|
|
1921
|
+
const packageData = {
|
|
1922
|
+
version: version};
|
|
1923
|
+
|
|
1924
|
+
function $1(Ut) {
|
|
1925
|
+
return Ut && Ut.__esModule && Object.prototype.hasOwnProperty.call(Ut, "default") ? Ut.default : Ut;
|
|
1926
|
+
}
|
|
1927
|
+
var S0 = { exports: {} }, Ob = { exports: {} }, P1;
|
|
1928
|
+
function Q1() {
|
|
1929
|
+
return P1 || (P1 = 1, (function(Ut) {
|
|
1930
|
+
Ut.exports = function(m) {
|
|
1931
|
+
function et(t, r, a, l) {
|
|
1932
|
+
return new Fe(t, r, a, l);
|
|
1933
|
+
}
|
|
1934
|
+
function zf() {
|
|
1935
|
+
}
|
|
1140
1936
|
function F(t) {
|
|
1141
1937
|
var r = "https://react.dev/errors/" + t;
|
|
1142
1938
|
if (1 < arguments.length) {
|
|
@@ -13319,15 +14115,16 @@ function swapInteractivity(store, object, newObject) {
|
|
|
13319
14115
|
pointerState.hovered.set(makeId(next), next);
|
|
13320
14116
|
}
|
|
13321
14117
|
});
|
|
13322
|
-
const captureData
|
|
13323
|
-
|
|
13324
|
-
|
|
13325
|
-
pointerState.captured.
|
|
14118
|
+
for (const [key, captureData] of Array.from(pointerState.captured)) {
|
|
14119
|
+
const { intersection } = captureData;
|
|
14120
|
+
if (key !== object && intersection.object !== object && intersection.eventObject !== object) continue;
|
|
14121
|
+
if (key === object) pointerState.captured.delete(key);
|
|
14122
|
+
pointerState.captured.set(key === object ? newObject : key, {
|
|
13326
14123
|
...captureData,
|
|
13327
14124
|
intersection: {
|
|
13328
|
-
...
|
|
13329
|
-
object:
|
|
13330
|
-
eventObject:
|
|
14125
|
+
...intersection,
|
|
14126
|
+
object: intersection.object === object ? newObject : intersection.object,
|
|
14127
|
+
eventObject: intersection.eventObject === object ? newObject : intersection.eventObject
|
|
13331
14128
|
}
|
|
13332
14129
|
});
|
|
13333
14130
|
}
|
|
@@ -13856,10 +14653,11 @@ const catalogue = globalThis[R3F_CATALOGUE] ?? (globalThis[R3F_CATALOGUE] = {});
|
|
|
13856
14653
|
const R3F_EXTEND_ID = Symbol.for("@react-three/fiber.extendId");
|
|
13857
14654
|
const ids = globalThis;
|
|
13858
14655
|
const toPascalCase = (type) => `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
13859
|
-
const isConstructor = (object) => typeof object === "function";
|
|
14656
|
+
const isConstructor$1 = (object) => typeof object === "function";
|
|
13860
14657
|
function extend(objects) {
|
|
13861
|
-
if (isConstructor(objects)) {
|
|
13862
|
-
|
|
14658
|
+
if (isConstructor$1(objects)) {
|
|
14659
|
+
let id = ids[R3F_EXTEND_ID] ?? 0;
|
|
14660
|
+
while (`${id}` in catalogue) id++;
|
|
13863
14661
|
ids[R3F_EXTEND_ID] = id + 1;
|
|
13864
14662
|
const Component = `${id}`;
|
|
13865
14663
|
catalogue[Component] = objects;
|
|
@@ -13867,15 +14665,14 @@ function extend(objects) {
|
|
|
13867
14665
|
} else {
|
|
13868
14666
|
for (const name in objects) {
|
|
13869
14667
|
const object = objects[name];
|
|
13870
|
-
if (isConstructor(object)) catalogue[name] = object;
|
|
14668
|
+
if (isConstructor$1(object)) catalogue[name] = object;
|
|
13871
14669
|
}
|
|
13872
14670
|
}
|
|
13873
14671
|
}
|
|
13874
|
-
|
|
13875
14672
|
function resolveConstructor(name, root) {
|
|
13876
14673
|
if (Object.prototype.hasOwnProperty.call(catalogue, name)) return catalogue[name];
|
|
13877
14674
|
const object = root.getState().internal.support?.three[name];
|
|
13878
|
-
return isConstructor(object) ? object : void 0;
|
|
14675
|
+
return isConstructor$1(object) ? object : void 0;
|
|
13879
14676
|
}
|
|
13880
14677
|
|
|
13881
14678
|
function createReconciler(config) {
|
|
@@ -13912,6 +14709,7 @@ function hideInstance(instance) {
|
|
|
13912
14709
|
if (instance.props.attach && instance.parent?.object) {
|
|
13913
14710
|
detach(instance.parent, instance);
|
|
13914
14711
|
} else if (isObject3D(instance.object)) {
|
|
14712
|
+
instance.previousVisible = instance.object.visible;
|
|
13915
14713
|
instance.object.visible = false;
|
|
13916
14714
|
}
|
|
13917
14715
|
instance.isHidden = true;
|
|
@@ -13922,9 +14720,10 @@ function unhideInstance(instance) {
|
|
|
13922
14720
|
if (instance.isHidden) {
|
|
13923
14721
|
if (instance.props.attach && instance.parent?.object) {
|
|
13924
14722
|
attach(instance.parent, instance);
|
|
13925
|
-
} else if (isObject3D(instance.object)
|
|
13926
|
-
instance.object.visible = true;
|
|
14723
|
+
} else if (isObject3D(instance.object)) {
|
|
14724
|
+
instance.object.visible = instance.previousVisible ?? true;
|
|
13927
14725
|
}
|
|
14726
|
+
instance.previousVisible = void 0;
|
|
13928
14727
|
instance.isHidden = false;
|
|
13929
14728
|
invalidateInstance(instance);
|
|
13930
14729
|
}
|
|
@@ -13997,6 +14796,7 @@ function disposeOnIdle(object) {
|
|
|
13997
14796
|
}
|
|
13998
14797
|
function removeChild(parent, child, dispose) {
|
|
13999
14798
|
if (!child) return;
|
|
14799
|
+
const wasLinked = !!child.parent;
|
|
14000
14800
|
child.parent = null;
|
|
14001
14801
|
const childIndex = parent.children.indexOf(child);
|
|
14002
14802
|
if (childIndex !== -1) parent.children.splice(childIndex, 1);
|
|
@@ -14016,7 +14816,10 @@ function removeChild(parent, child, dispose) {
|
|
|
14016
14816
|
if (shouldDispose && child.type !== "primitive" && child.object.type !== "Scene") {
|
|
14017
14817
|
disposeOnIdle(child.object);
|
|
14018
14818
|
}
|
|
14019
|
-
if (dispose === void 0)
|
|
14819
|
+
if (dispose === void 0 && wasLinked) {
|
|
14820
|
+
const state = findInitialRoot(child).getState();
|
|
14821
|
+
if (state.internal.active && state.internal.frames === 0) state.invalidate();
|
|
14822
|
+
}
|
|
14020
14823
|
}
|
|
14021
14824
|
function setFiberRef(fiber, publicInstance) {
|
|
14022
14825
|
for (const _fiber of [fiber, fiber.alternate]) {
|
|
@@ -14337,462 +15140,125 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14337
15140
|
rendererPackageName: "@react-three/fiber",
|
|
14338
15141
|
rendererVersion: packageData.version,
|
|
14339
15142
|
// 19.2 Reconciler
|
|
14340
|
-
// https://github.com/facebook/react/pull/31975
|
|
14341
|
-
// https://github.com/facebook/react/pull/31999
|
|
14342
|
-
applyViewTransitionName(_instance, _name, _className) {
|
|
14343
|
-
},
|
|
14344
|
-
restoreViewTransitionName(_instance, _props) {
|
|
14345
|
-
},
|
|
14346
|
-
cancelViewTransitionName(_instance, _name, _props) {
|
|
14347
|
-
},
|
|
14348
|
-
cancelRootViewTransitionName(_rootContainer) {
|
|
14349
|
-
},
|
|
14350
|
-
restoreRootViewTransitionName(_rootContainer) {
|
|
14351
|
-
},
|
|
14352
|
-
InstanceMeasurement: null,
|
|
14353
|
-
measureInstance: (_instance) => null,
|
|
14354
|
-
wasInstanceInViewport: (_measurement) => true,
|
|
14355
|
-
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
14356
|
-
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
14357
|
-
// https://github.com/facebook/react/pull/32002
|
|
14358
|
-
// https://github.com/facebook/react/pull/34486
|
|
14359
|
-
suspendOnActiveViewTransition(_state, _container) {
|
|
14360
|
-
},
|
|
14361
|
-
// https://github.com/facebook/react/pull/32451
|
|
14362
|
-
// https://github.com/facebook/react/pull/32760
|
|
14363
|
-
// React hands the whole commit to the host when a transition touches a <ViewTransition> subtree.
|
|
14364
|
-
// three.js has nothing to animate between commits, so this mirrors the react-dom fallback for
|
|
14365
|
-
// browsers without document.startViewTransition and flushes the commit synchronously.
|
|
14366
|
-
startViewTransition(_suspendedState, _rootContainer, _transitionTypes, mutationCallback, layoutCallback, _afterMutationCallback, spawnedWorkCallback, _passiveCallback, _errorCallback, _blockedCallback, finishedAnimation) {
|
|
14367
|
-
mutationCallback();
|
|
14368
|
-
layoutCallback();
|
|
14369
|
-
finishedAnimation?.();
|
|
14370
|
-
spawnedWorkCallback();
|
|
14371
|
-
return null;
|
|
14372
|
-
},
|
|
14373
|
-
startGestureTransition(_suspendedState, _rootContainer, _timeline, _rangeStart, _rangeEnd, _transitionTypes, mutationCallback, animateCallback, _errorCallback, finishedAnimation) {
|
|
14374
|
-
mutationCallback();
|
|
14375
|
-
animateCallback();
|
|
14376
|
-
finishedAnimation?.();
|
|
14377
|
-
return null;
|
|
14378
|
-
},
|
|
14379
|
-
stopViewTransition(_transition) {
|
|
14380
|
-
},
|
|
14381
|
-
// https://github.com/facebook/react/pull/35564
|
|
14382
|
-
// Only reached with a non-null transition from startViewTransition, which never returns one here
|
|
14383
|
-
addViewTransitionFinishedListener(_transition, callback) {
|
|
14384
|
-
callback();
|
|
14385
|
-
},
|
|
14386
|
-
// https://github.com/facebook/react/pull/32038
|
|
14387
|
-
createViewTransitionInstance: (_name) => null,
|
|
14388
|
-
// https://github.com/facebook/react/pull/32379
|
|
14389
|
-
// https://github.com/facebook/react/pull/32786
|
|
14390
|
-
getCurrentGestureOffset(_provider) {
|
|
14391
|
-
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
14392
|
-
},
|
|
14393
|
-
// https://github.com/facebook/react/pull/32500
|
|
14394
|
-
cloneMutableInstance(instance, _keepChildren) {
|
|
14395
|
-
return instance;
|
|
14396
|
-
},
|
|
14397
|
-
cloneMutableTextInstance(textInstance) {
|
|
14398
|
-
return textInstance;
|
|
14399
|
-
},
|
|
14400
|
-
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
14401
|
-
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
14402
|
-
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
14403
|
-
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
14404
|
-
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
14405
|
-
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
14406
|
-
cloneRootViewTransitionContainer(_rootContainer) {
|
|
14407
|
-
},
|
|
14408
|
-
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
14409
|
-
},
|
|
14410
|
-
// https://github.com/facebook/react/pull/32465
|
|
14411
|
-
createFragmentInstance: (_fiber) => null,
|
|
14412
|
-
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
14413
|
-
},
|
|
14414
|
-
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
14415
|
-
},
|
|
14416
|
-
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
14417
|
-
},
|
|
14418
|
-
// https://github.com/facebook/react/pull/32653
|
|
14419
|
-
measureClonedInstance: (_instance) => null,
|
|
14420
|
-
// https://github.com/facebook/react/pull/32819
|
|
14421
|
-
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
14422
|
-
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
14423
|
-
// https://github.com/facebook/react/pull/34486
|
|
14424
|
-
startSuspendingCommit: () => null,
|
|
14425
|
-
// https://github.com/facebook/react/pull/34522
|
|
14426
|
-
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14427
|
-
});
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
14431
|
-
if (!stack) return false;
|
|
14432
|
-
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
14433
|
-
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
14434
|
-
}
|
|
14435
|
-
|
|
14436
|
-
const createStore = (invalidate, advance) => {
|
|
14437
|
-
const rootStore = createWithEqualityFn((set, get) => {
|
|
14438
|
-
let position;
|
|
14439
|
-
let defaultTarget;
|
|
14440
|
-
let tempTarget;
|
|
14441
|
-
function getCurrentViewport(camera = get().camera, target = void 0, size = get().size) {
|
|
14442
|
-
const { Vector3 } = getThree();
|
|
14443
|
-
position ?? (position = new Vector3());
|
|
14444
|
-
defaultTarget ?? (defaultTarget = new Vector3());
|
|
14445
|
-
tempTarget ?? (tempTarget = new Vector3());
|
|
14446
|
-
target ?? (target = defaultTarget);
|
|
14447
|
-
const { width, height, top, left } = size;
|
|
14448
|
-
const aspect = width / height;
|
|
14449
|
-
if (target.isVector3) tempTarget.copy(target);
|
|
14450
|
-
else tempTarget.set(...target);
|
|
14451
|
-
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
14452
|
-
if (isOrthographicCamera(camera)) {
|
|
14453
|
-
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
14454
|
-
} else {
|
|
14455
|
-
const fov = camera.fov * Math.PI / 180;
|
|
14456
|
-
const h = 2 * Math.tan(fov / 2) * distance;
|
|
14457
|
-
const w = h * (width / height);
|
|
14458
|
-
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
14459
|
-
}
|
|
14460
|
-
}
|
|
14461
|
-
let performanceTimeout = void 0;
|
|
14462
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
14463
|
-
const rootState = {
|
|
14464
|
-
set,
|
|
14465
|
-
get,
|
|
14466
|
-
// Mock objects that have to be configured
|
|
14467
|
-
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
14468
|
-
primaryStore: null,
|
|
14469
|
-
gl: null,
|
|
14470
|
-
renderer: null,
|
|
14471
|
-
camera: null,
|
|
14472
|
-
// frustum, pointer and mouse are three objects; configure() creates them with the renderer
|
|
14473
|
-
frustum: null,
|
|
14474
|
-
autoUpdateFrustum: true,
|
|
14475
|
-
raycaster: null,
|
|
14476
|
-
events: {
|
|
14477
|
-
priority: 1,
|
|
14478
|
-
enabled: true,
|
|
14479
|
-
connected: false,
|
|
14480
|
-
frameTimedRaycasts: true,
|
|
14481
|
-
alwaysFireOnScroll: true,
|
|
14482
|
-
updateOnFrame: false
|
|
14483
|
-
},
|
|
14484
|
-
scene: null,
|
|
14485
|
-
rootScene: null,
|
|
14486
|
-
xr: null,
|
|
14487
|
-
inspector: null,
|
|
14488
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
14489
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
14490
|
-
textureColorSpace: "srgb",
|
|
14491
|
-
// THREE.SRGBColorSpace
|
|
14492
|
-
isLegacy: false,
|
|
14493
|
-
webGPUSupported: false,
|
|
14494
|
-
isNative: false,
|
|
14495
|
-
controls: null,
|
|
14496
|
-
pointer: null,
|
|
14497
|
-
mouse: null,
|
|
14498
|
-
frameloop: "always",
|
|
14499
|
-
onPointerMissed: void 0,
|
|
14500
|
-
onDragOverMissed: void 0,
|
|
14501
|
-
onDropMissed: void 0,
|
|
14502
|
-
performance: {
|
|
14503
|
-
current: 1,
|
|
14504
|
-
min: 0.5,
|
|
14505
|
-
max: 1,
|
|
14506
|
-
debounce: 200,
|
|
14507
|
-
regress: () => {
|
|
14508
|
-
const state2 = get();
|
|
14509
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
14510
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
14511
|
-
performanceTimeout = setTimeout(
|
|
14512
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
14513
|
-
state2.performance.debounce
|
|
14514
|
-
);
|
|
14515
|
-
}
|
|
14516
|
-
},
|
|
14517
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
14518
|
-
viewport: {
|
|
14519
|
-
initialDpr: 0,
|
|
14520
|
-
dpr: 0,
|
|
14521
|
-
width: 0,
|
|
14522
|
-
height: 0,
|
|
14523
|
-
top: 0,
|
|
14524
|
-
left: 0,
|
|
14525
|
-
aspect: 0,
|
|
14526
|
-
distance: 0,
|
|
14527
|
-
factor: 0,
|
|
14528
|
-
getCurrentViewport
|
|
14529
|
-
},
|
|
14530
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
14531
|
-
setSize: (width, height, top, left) => {
|
|
14532
|
-
const state2 = get();
|
|
14533
|
-
if (width === void 0) {
|
|
14534
|
-
set({ _sizeImperative: false });
|
|
14535
|
-
if (state2._sizeProps) {
|
|
14536
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
14537
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
14538
|
-
const currentSize = state2.size;
|
|
14539
|
-
const newSize = {
|
|
14540
|
-
width: propW ?? currentSize.width,
|
|
14541
|
-
height: propH ?? currentSize.height,
|
|
14542
|
-
top: currentSize.top,
|
|
14543
|
-
left: currentSize.left
|
|
14544
|
-
};
|
|
14545
|
-
set((s) => ({
|
|
14546
|
-
size: newSize,
|
|
14547
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
14548
|
-
}));
|
|
14549
|
-
get().invalidate();
|
|
14550
|
-
}
|
|
14551
|
-
}
|
|
14552
|
-
return;
|
|
14553
|
-
}
|
|
14554
|
-
const w = width;
|
|
14555
|
-
const h = height ?? width;
|
|
14556
|
-
const t = top ?? state2.size.top;
|
|
14557
|
-
const l = left ?? state2.size.left;
|
|
14558
|
-
const size = { width: w, height: h, top: t, left: l };
|
|
14559
|
-
set((s) => ({
|
|
14560
|
-
size,
|
|
14561
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
14562
|
-
_sizeImperative: true
|
|
14563
|
-
}));
|
|
14564
|
-
get().invalidate();
|
|
14565
|
-
},
|
|
14566
|
-
setDpr: (dpr) => set((state2) => {
|
|
14567
|
-
const resolved = calculateDpr(dpr);
|
|
14568
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
14569
|
-
}),
|
|
14570
|
-
setFrameloop: (frameloop = "always") => {
|
|
14571
|
-
const rootId = get().internal.rootId;
|
|
14572
|
-
if (rootId) getScheduler().setRootFrameloop(rootId, frameloop);
|
|
14573
|
-
set(() => ({ frameloop }));
|
|
14574
|
-
},
|
|
14575
|
-
setError: (error) => set(() => ({ error })),
|
|
14576
|
-
error: null,
|
|
14577
|
-
//* Texture registry (useTextures) ==============================
|
|
14578
|
-
// TSL fields (uniforms, nodes, ..., renderPipeline) are added by @react-three/tsl's root extension.
|
|
14579
|
-
textures: /* @__PURE__ */ new Map(),
|
|
14580
|
-
_textureRefs: /* @__PURE__ */ new Map(),
|
|
14581
|
-
_sizeImperative: false,
|
|
14582
|
-
_sizeProps: null,
|
|
14583
|
-
previousRoot: void 0,
|
|
14584
|
-
internal: {
|
|
14585
|
-
// Events
|
|
14586
|
-
interaction: [],
|
|
14587
|
-
subscribers: [],
|
|
14588
|
-
// Per-pointer state (new unified structure)
|
|
14589
|
-
pointerMap: /* @__PURE__ */ new Map(),
|
|
14590
|
-
pointerDirty: /* @__PURE__ */ new Map(),
|
|
14591
|
-
lastEvent: React.createRef(),
|
|
14592
|
-
// Deprecated but kept for backwards compatibility
|
|
14593
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
14594
|
-
initialClick: [0, 0],
|
|
14595
|
-
initialHits: [],
|
|
14596
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
14597
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
14598
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
14599
|
-
// Occlusion system (WebGPU only)
|
|
14600
|
-
occlusionEnabled: false,
|
|
14601
|
-
occlusionObserver: null,
|
|
14602
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
14603
|
-
helperGroup: null,
|
|
14604
|
-
// Updates
|
|
14605
|
-
active: false,
|
|
14606
|
-
frames: 0,
|
|
14607
|
-
priority: 0,
|
|
14608
|
-
subscribe: (ref, priority, store) => {
|
|
14609
|
-
const internal = get().internal;
|
|
14610
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
14611
|
-
internal.subscribers.push({ ref, priority, store });
|
|
14612
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14613
|
-
return () => {
|
|
14614
|
-
const internal2 = get().internal;
|
|
14615
|
-
if (internal2?.subscribers) {
|
|
14616
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14617
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14618
|
-
}
|
|
14619
|
-
};
|
|
14620
|
-
},
|
|
14621
|
-
// Renderer Storage (single source of truth)
|
|
14622
|
-
actualRenderer: null,
|
|
14623
|
-
// The renderer support configure() loads for this root
|
|
14624
|
-
support: null,
|
|
14625
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14626
|
-
scheduler: null,
|
|
14627
|
-
// Replaces the default render call when set (see setRenderOverride)
|
|
14628
|
-
renderOverride: null
|
|
14629
|
-
}
|
|
14630
|
-
};
|
|
14631
|
-
return rootState;
|
|
14632
|
-
});
|
|
14633
|
-
const state = rootStore.getState();
|
|
14634
|
-
Object.defineProperty(state, "gl", {
|
|
14635
|
-
get() {
|
|
14636
|
-
const currentState = rootStore.getState();
|
|
14637
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14638
|
-
const stack = new Error().stack || "";
|
|
14639
|
-
if (!isInternalRendererAccess(stack)) {
|
|
14640
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14641
|
-
notifyDepreciated({
|
|
14642
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
14643
|
-
body: "Please use state.renderer instead. state.gl is deprecated and will be removed in future versions.\n\nFor backwards compatibility, state.gl currently maps to state.renderer, but this may cause issues with libraries expecting WebGLRenderer.\n\nAccessed from:\n" + cleanedStack
|
|
14644
|
-
});
|
|
14645
|
-
}
|
|
14646
|
-
}
|
|
14647
|
-
return currentState.internal.actualRenderer;
|
|
14648
|
-
},
|
|
14649
|
-
set(value) {
|
|
14650
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
14651
|
-
},
|
|
14652
|
-
enumerable: true,
|
|
14653
|
-
configurable: true
|
|
14654
|
-
});
|
|
14655
|
-
Object.defineProperty(state, "renderer", {
|
|
14656
|
-
get() {
|
|
14657
|
-
return rootStore.getState().internal.actualRenderer;
|
|
14658
|
-
},
|
|
14659
|
-
set(value) {
|
|
14660
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
14661
|
-
},
|
|
14662
|
-
enumerable: true,
|
|
14663
|
-
configurable: true
|
|
14664
|
-
});
|
|
14665
|
-
let oldScene = state.scene;
|
|
14666
|
-
rootStore.subscribe(() => {
|
|
14667
|
-
const currentState = rootStore.getState();
|
|
14668
|
-
const { scene, rootScene, set } = currentState;
|
|
14669
|
-
if (scene !== oldScene) {
|
|
14670
|
-
oldScene = scene;
|
|
14671
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
14672
|
-
set({ rootScene: scene });
|
|
14673
|
-
}
|
|
14674
|
-
}
|
|
14675
|
-
});
|
|
14676
|
-
let oldSize = state.size;
|
|
14677
|
-
let oldDpr = state.viewport.dpr;
|
|
14678
|
-
let oldCamera = state.camera;
|
|
14679
|
-
rootStore.subscribe(() => {
|
|
14680
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14681
|
-
const actualRenderer = internal.actualRenderer;
|
|
14682
|
-
const canvasTarget = internal.canvasTarget;
|
|
14683
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14684
|
-
oldSize = size;
|
|
14685
|
-
oldDpr = viewport.dpr;
|
|
14686
|
-
updateCamera(camera, size);
|
|
14687
|
-
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14688
|
-
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14689
|
-
resizeTarget.setSize(size.width, size.height, false);
|
|
14690
|
-
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14691
|
-
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
14692
|
-
}
|
|
14693
|
-
if (camera !== oldCamera) {
|
|
14694
|
-
oldCamera = camera;
|
|
14695
|
-
const { rootScene } = rootStore.getState();
|
|
14696
|
-
if (camera && rootScene && !camera.parent) {
|
|
14697
|
-
rootScene.add(camera);
|
|
14698
|
-
}
|
|
14699
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14700
|
-
const currentState = rootStore.getState();
|
|
14701
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
14702
|
-
updateFrustum(camera, currentState.frustum);
|
|
14703
|
-
}
|
|
14704
|
-
}
|
|
14705
|
-
});
|
|
14706
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
14707
|
-
return rootStore;
|
|
14708
|
-
};
|
|
14709
|
-
|
|
14710
|
-
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
14711
|
-
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
14712
|
-
function registerPrimary(id, renderer, store) {
|
|
14713
|
-
if (primaryRegistry.has(id)) {
|
|
14714
|
-
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
14715
|
-
}
|
|
14716
|
-
const entry = { renderer, store };
|
|
14717
|
-
primaryRegistry.set(id, entry);
|
|
14718
|
-
const subscribers = pendingSubscribers.get(id);
|
|
14719
|
-
if (subscribers) {
|
|
14720
|
-
subscribers.forEach((callback) => callback(entry));
|
|
14721
|
-
pendingSubscribers.delete(id);
|
|
14722
|
-
}
|
|
14723
|
-
return () => {
|
|
14724
|
-
const currentEntry = primaryRegistry.get(id);
|
|
14725
|
-
if (currentEntry?.renderer === renderer) {
|
|
14726
|
-
primaryRegistry.delete(id);
|
|
14727
|
-
}
|
|
14728
|
-
};
|
|
14729
|
-
}
|
|
14730
|
-
function getPrimary(id) {
|
|
14731
|
-
return primaryRegistry.get(id);
|
|
14732
|
-
}
|
|
14733
|
-
function waitForPrimary(id, timeout = 5e3) {
|
|
14734
|
-
const existing = primaryRegistry.get(id);
|
|
14735
|
-
if (existing) {
|
|
14736
|
-
return Promise.resolve(existing);
|
|
14737
|
-
}
|
|
14738
|
-
return new Promise((resolve, reject) => {
|
|
14739
|
-
const timeoutId = setTimeout(() => {
|
|
14740
|
-
const subscribers = pendingSubscribers.get(id);
|
|
14741
|
-
if (subscribers) {
|
|
14742
|
-
const index = subscribers.indexOf(callback);
|
|
14743
|
-
if (index !== -1) subscribers.splice(index, 1);
|
|
14744
|
-
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
14745
|
-
}
|
|
14746
|
-
reject(new Error(`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}"> is mounted.`));
|
|
14747
|
-
}, timeout);
|
|
14748
|
-
const callback = (entry) => {
|
|
14749
|
-
clearTimeout(timeoutId);
|
|
14750
|
-
resolve(entry);
|
|
14751
|
-
};
|
|
14752
|
-
if (!pendingSubscribers.has(id)) {
|
|
14753
|
-
pendingSubscribers.set(id, []);
|
|
14754
|
-
}
|
|
14755
|
-
pendingSubscribers.get(id).push(callback);
|
|
14756
|
-
});
|
|
14757
|
-
}
|
|
14758
|
-
function hasPrimary(id) {
|
|
14759
|
-
return primaryRegistry.has(id);
|
|
14760
|
-
}
|
|
14761
|
-
function unregisterPrimary(id) {
|
|
14762
|
-
primaryRegistry.delete(id);
|
|
14763
|
-
}
|
|
14764
|
-
function getPrimaryIds() {
|
|
14765
|
-
return Array.from(primaryRegistry.keys());
|
|
15143
|
+
// https://github.com/facebook/react/pull/31975
|
|
15144
|
+
// https://github.com/facebook/react/pull/31999
|
|
15145
|
+
applyViewTransitionName(_instance, _name, _className) {
|
|
15146
|
+
},
|
|
15147
|
+
restoreViewTransitionName(_instance, _props) {
|
|
15148
|
+
},
|
|
15149
|
+
cancelViewTransitionName(_instance, _name, _props) {
|
|
15150
|
+
},
|
|
15151
|
+
cancelRootViewTransitionName(_rootContainer) {
|
|
15152
|
+
},
|
|
15153
|
+
restoreRootViewTransitionName(_rootContainer) {
|
|
15154
|
+
},
|
|
15155
|
+
InstanceMeasurement: null,
|
|
15156
|
+
measureInstance: (_instance) => null,
|
|
15157
|
+
wasInstanceInViewport: (_measurement) => true,
|
|
15158
|
+
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
15159
|
+
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
15160
|
+
// https://github.com/facebook/react/pull/32002
|
|
15161
|
+
// https://github.com/facebook/react/pull/34486
|
|
15162
|
+
suspendOnActiveViewTransition(_state, _container) {
|
|
15163
|
+
},
|
|
15164
|
+
// https://github.com/facebook/react/pull/32451
|
|
15165
|
+
// https://github.com/facebook/react/pull/32760
|
|
15166
|
+
// React hands the whole commit to the host when a transition touches a <ViewTransition> subtree.
|
|
15167
|
+
// three.js has nothing to animate between commits, so this mirrors the react-dom fallback for
|
|
15168
|
+
// browsers without document.startViewTransition and flushes the commit synchronously.
|
|
15169
|
+
startViewTransition(_suspendedState, _rootContainer, _transitionTypes, mutationCallback, layoutCallback, _afterMutationCallback, spawnedWorkCallback, _passiveCallback, _errorCallback, _blockedCallback, finishedAnimation) {
|
|
15170
|
+
mutationCallback();
|
|
15171
|
+
layoutCallback();
|
|
15172
|
+
finishedAnimation?.();
|
|
15173
|
+
spawnedWorkCallback();
|
|
15174
|
+
return null;
|
|
15175
|
+
},
|
|
15176
|
+
startGestureTransition(_suspendedState, _rootContainer, _timeline, _rangeStart, _rangeEnd, _transitionTypes, mutationCallback, animateCallback, _errorCallback, finishedAnimation) {
|
|
15177
|
+
mutationCallback();
|
|
15178
|
+
animateCallback();
|
|
15179
|
+
finishedAnimation?.();
|
|
15180
|
+
return null;
|
|
15181
|
+
},
|
|
15182
|
+
stopViewTransition(_transition) {
|
|
15183
|
+
},
|
|
15184
|
+
// https://github.com/facebook/react/pull/35564
|
|
15185
|
+
// Only reached with a non-null transition from startViewTransition, which never returns one here
|
|
15186
|
+
addViewTransitionFinishedListener(_transition, callback) {
|
|
15187
|
+
callback();
|
|
15188
|
+
},
|
|
15189
|
+
// https://github.com/facebook/react/pull/32038
|
|
15190
|
+
createViewTransitionInstance: (_name) => null,
|
|
15191
|
+
// https://github.com/facebook/react/pull/32379
|
|
15192
|
+
// https://github.com/facebook/react/pull/32786
|
|
15193
|
+
getCurrentGestureOffset(_provider) {
|
|
15194
|
+
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
15195
|
+
},
|
|
15196
|
+
// https://github.com/facebook/react/pull/32500
|
|
15197
|
+
cloneMutableInstance(instance, _keepChildren) {
|
|
15198
|
+
return instance;
|
|
15199
|
+
},
|
|
15200
|
+
cloneMutableTextInstance(textInstance) {
|
|
15201
|
+
return textInstance;
|
|
15202
|
+
},
|
|
15203
|
+
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
15204
|
+
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
15205
|
+
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
15206
|
+
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
15207
|
+
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
15208
|
+
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
15209
|
+
cloneRootViewTransitionContainer(_rootContainer) {
|
|
15210
|
+
},
|
|
15211
|
+
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
15212
|
+
},
|
|
15213
|
+
// https://github.com/facebook/react/pull/32465
|
|
15214
|
+
createFragmentInstance: (_fiber) => null,
|
|
15215
|
+
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
15216
|
+
},
|
|
15217
|
+
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
15218
|
+
},
|
|
15219
|
+
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
15220
|
+
},
|
|
15221
|
+
// https://github.com/facebook/react/pull/32653
|
|
15222
|
+
measureClonedInstance: (_instance) => null,
|
|
15223
|
+
// https://github.com/facebook/react/pull/32819
|
|
15224
|
+
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
15225
|
+
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
15226
|
+
// https://github.com/facebook/react/pull/34486
|
|
15227
|
+
startSuspendingCommit: () => null,
|
|
15228
|
+
// https://github.com/facebook/react/pull/34522
|
|
15229
|
+
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
15230
|
+
});
|
|
15231
|
+
function flushSync(fn) {
|
|
15232
|
+
return reconciler.flushSyncFromReconciler(fn);
|
|
14766
15233
|
}
|
|
14767
15234
|
|
|
14768
|
-
const
|
|
15235
|
+
const noop = () => {
|
|
15236
|
+
};
|
|
14769
15237
|
const _roots = /* @__PURE__ */ new Map();
|
|
14770
|
-
function
|
|
14771
|
-
const state =
|
|
14772
|
-
|
|
14773
|
-
|
|
14774
|
-
|
|
14775
|
-
|
|
14776
|
-
|
|
14777
|
-
|
|
14778
|
-
|
|
14779
|
-
|
|
14780
|
-
|
|
14781
|
-
|
|
14782
|
-
|
|
14783
|
-
|
|
14784
|
-
|
|
14785
|
-
|
|
14786
|
-
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
14790
|
-
|
|
14791
|
-
|
|
14792
|
-
|
|
14793
|
-
};
|
|
15238
|
+
function transitionRoot(root, event) {
|
|
15239
|
+
const state = root.state;
|
|
15240
|
+
switch (event.type) {
|
|
15241
|
+
case "use":
|
|
15242
|
+
if (state.status === "disposed") return false;
|
|
15243
|
+
if (state.status === "closing") {
|
|
15244
|
+
root.store.getState().internal.active = true;
|
|
15245
|
+
state.settle();
|
|
15246
|
+
}
|
|
15247
|
+
root.state = { status: "open" };
|
|
15248
|
+
return true;
|
|
15249
|
+
case "unmount": {
|
|
15250
|
+
if (state.status === "disposed") return false;
|
|
15251
|
+
if (state.status === "closing") state.settle();
|
|
15252
|
+
const { promise, resolve } = deferred();
|
|
15253
|
+
root.state = { status: "closing", token: event.token, settled: promise, settle: resolve };
|
|
15254
|
+
return true;
|
|
15255
|
+
}
|
|
15256
|
+
case "dispose":
|
|
15257
|
+
if (state.status !== "closing" || state.token !== event.token) return false;
|
|
15258
|
+
root.state = { status: "disposed" };
|
|
15259
|
+
state.settle();
|
|
15260
|
+
return true;
|
|
14794
15261
|
}
|
|
14795
|
-
return { width: 0, height: 0, top: 0, left: 0, ...size };
|
|
14796
15262
|
}
|
|
14797
15263
|
function createRoot(canvas, provider) {
|
|
14798
15264
|
const prevRoot = _roots.get(canvas);
|
|
@@ -14830,540 +15296,615 @@ function createRoot(canvas, provider) {
|
|
|
14830
15296
|
null
|
|
14831
15297
|
// transitionCallbacks
|
|
14832
15298
|
);
|
|
14833
|
-
|
|
14834
|
-
|
|
14835
|
-
|
|
14836
|
-
|
|
14837
|
-
|
|
14838
|
-
|
|
14839
|
-
|
|
14840
|
-
|
|
14841
|
-
|
|
14842
|
-
|
|
14843
|
-
|
|
14844
|
-
|
|
14845
|
-
|
|
14846
|
-
|
|
14847
|
-
|
|
14848
|
-
|
|
14849
|
-
|
|
14850
|
-
|
|
14851
|
-
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
14855
|
-
|
|
14856
|
-
|
|
14857
|
-
|
|
14858
|
-
|
|
14859
|
-
|
|
14860
|
-
|
|
14861
|
-
|
|
14862
|
-
|
|
14863
|
-
|
|
14864
|
-
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
|
|
14869
|
-
|
|
14870
|
-
|
|
14871
|
-
|
|
14872
|
-
|
|
14873
|
-
|
|
14874
|
-
|
|
14875
|
-
|
|
14876
|
-
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14880
|
-
|
|
14881
|
-
|
|
14882
|
-
|
|
14883
|
-
|
|
14884
|
-
|
|
14885
|
-
|
|
14886
|
-
|
|
14887
|
-
|
|
14888
|
-
|
|
14889
|
-
|
|
14890
|
-
|
|
14891
|
-
|
|
14892
|
-
|
|
14893
|
-
|
|
14894
|
-
|
|
14895
|
-
|
|
14896
|
-
|
|
14897
|
-
|
|
14898
|
-
|
|
14899
|
-
|
|
14900
|
-
|
|
14901
|
-
|
|
14902
|
-
}
|
|
14903
|
-
|
|
14904
|
-
|
|
14905
|
-
|
|
14906
|
-
|
|
14907
|
-
|
|
14908
|
-
|
|
14909
|
-
|
|
14910
|
-
|
|
14911
|
-
|
|
14912
|
-
|
|
15299
|
+
const root = prevRoot || {
|
|
15300
|
+
fiber,
|
|
15301
|
+
store,
|
|
15302
|
+
state: { status: "open" },
|
|
15303
|
+
ready: fulfilled(void 0),
|
|
15304
|
+
configuration: {}
|
|
15305
|
+
};
|
|
15306
|
+
if (!prevRoot) _roots.set(canvas, root);
|
|
15307
|
+
if (!prevRoot) root.configuration.apply = createRootConfiguration(store, canvas);
|
|
15308
|
+
let mounted = false;
|
|
15309
|
+
return {
|
|
15310
|
+
get ready() {
|
|
15311
|
+
return root.ready;
|
|
15312
|
+
},
|
|
15313
|
+
configure(props = {}) {
|
|
15314
|
+
if (!transitionRoot(root, { type: "use" })) {
|
|
15315
|
+
return rejected(new Error("R3F: Cannot configure a root after it has unmounted (disposal has started)."));
|
|
15316
|
+
}
|
|
15317
|
+
const previous = root.ready;
|
|
15318
|
+
const { promise, resolve, reject } = deferred();
|
|
15319
|
+
root.ready = promise;
|
|
15320
|
+
const run = () => {
|
|
15321
|
+
try {
|
|
15322
|
+
const initialized = initializeRenderer(canvas, provider, store, props);
|
|
15323
|
+
const apply = () => {
|
|
15324
|
+
if (props.id) {
|
|
15325
|
+
for (const other of _roots.values()) {
|
|
15326
|
+
if (other !== root && other.state.status === "closing" && other.store.getState().internal.rootId === props.id) {
|
|
15327
|
+
other.state.settled.then(apply).catch(reject);
|
|
15328
|
+
return;
|
|
15329
|
+
}
|
|
15330
|
+
}
|
|
15331
|
+
}
|
|
15332
|
+
const previous2 = root.configuration.previous;
|
|
15333
|
+
root.configuration.apply(props);
|
|
15334
|
+
configureScheduler(store, props.id, props.scheduler, previous2?.scheduler);
|
|
15335
|
+
attachRootExtensions(store);
|
|
15336
|
+
root.configuration.previous = props;
|
|
15337
|
+
resolve(this);
|
|
15338
|
+
};
|
|
15339
|
+
if (isPromiseLike(initialized)) Promise.resolve(initialized).then(apply).catch(reject);
|
|
15340
|
+
else apply();
|
|
15341
|
+
} catch (error) {
|
|
15342
|
+
reject(error);
|
|
15343
|
+
}
|
|
15344
|
+
};
|
|
15345
|
+
if (previous.status === "pending") previous.then(run, reject);
|
|
15346
|
+
else run();
|
|
15347
|
+
return promise;
|
|
15348
|
+
},
|
|
15349
|
+
render(children) {
|
|
15350
|
+
if (!transitionRoot(root, { type: "use" })) return store;
|
|
15351
|
+
if (!store.getState().internal.actualRenderer && root.ready.status === "fulfilled") this.configure();
|
|
15352
|
+
if (root.ready.status === "rejected") throw root.ready.reason;
|
|
15353
|
+
const commit = () => {
|
|
15354
|
+
if (root.state.status !== "open" || root.ready.status === "rejected") return;
|
|
15355
|
+
if (root.ready.status === "pending") {
|
|
15356
|
+
root.ready.then(commit, logRecoverableError);
|
|
15357
|
+
return;
|
|
15358
|
+
}
|
|
15359
|
+
const onCreated = root.configuration.previous?.onCreated;
|
|
15360
|
+
const element = /* @__PURE__ */ jsx(Provider, { store, children, onCreated, rootElement: canvas });
|
|
15361
|
+
if (mounted) {
|
|
15362
|
+
reconciler.updateContainer(element, fiber, null, noop);
|
|
15363
|
+
return;
|
|
15364
|
+
}
|
|
15365
|
+
mounted = true;
|
|
15366
|
+
reconciler.updateContainerSync(element, fiber, null, noop);
|
|
15367
|
+
reconciler.flushSyncWork();
|
|
15368
|
+
};
|
|
15369
|
+
commit();
|
|
15370
|
+
return store;
|
|
15371
|
+
},
|
|
15372
|
+
unmount() {
|
|
15373
|
+
if (_roots.get(canvas) === root) unmountComponentAtNode(canvas);
|
|
15374
|
+
}
|
|
15375
|
+
};
|
|
15376
|
+
}
|
|
15377
|
+
function Provider({
|
|
15378
|
+
store,
|
|
15379
|
+
children,
|
|
15380
|
+
onCreated,
|
|
15381
|
+
rootElement
|
|
15382
|
+
}) {
|
|
15383
|
+
useIsomorphicLayoutEffect(() => {
|
|
15384
|
+
const state = store.getState();
|
|
15385
|
+
state.set((state2) => ({ internal: { ...state2.internal, active: true } }));
|
|
15386
|
+
if (onCreated) onCreated(state);
|
|
15387
|
+
if (!store.getState().events.connected) state.events.connect?.(rootElement);
|
|
15388
|
+
}, []);
|
|
15389
|
+
return /* @__PURE__ */ jsx(context.Provider, { value: store, children });
|
|
15390
|
+
}
|
|
15391
|
+
function unmountComponentAtNode(canvas, callback) {
|
|
15392
|
+
const claim = Symbol("unmount");
|
|
15393
|
+
const root = _roots.get(canvas);
|
|
15394
|
+
if (!root || !transitionRoot(root, { type: "unmount", token: claim })) return;
|
|
15395
|
+
root.store.getState().internal.active = false;
|
|
15396
|
+
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
15397
|
+
if (root.state.status !== "closing" || root.state.token !== claim) return;
|
|
15398
|
+
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
15399
|
+
if (root.state.status !== "closing" || root.state.token !== claim) return;
|
|
15400
|
+
if (root.ready.status === "pending") root.ready.then(teardown, teardown);
|
|
15401
|
+
else teardown();
|
|
15402
|
+
});
|
|
15403
|
+
});
|
|
15404
|
+
function teardown() {
|
|
15405
|
+
if (root.ready.status === "pending") {
|
|
15406
|
+
root.ready.then(teardown, teardown);
|
|
15407
|
+
return;
|
|
15408
|
+
}
|
|
15409
|
+
if (!transitionRoot(root, { type: "dispose", token: claim })) return;
|
|
15410
|
+
_roots.delete(canvas);
|
|
15411
|
+
const state = root.store.getState();
|
|
15412
|
+
const internal = state.internal;
|
|
15413
|
+
internal.active = false;
|
|
15414
|
+
const attempt = (step) => {
|
|
15415
|
+
try {
|
|
15416
|
+
return step();
|
|
15417
|
+
} catch (error) {
|
|
15418
|
+
console.warn("[R3F] Error while unmounting root; teardown may be incomplete:", error);
|
|
15419
|
+
}
|
|
15420
|
+
};
|
|
15421
|
+
attempt(() => internal.unwatchDpr?.());
|
|
15422
|
+
internal.unwatchDpr = void 0;
|
|
15423
|
+
attempt(() => internal.unregisterRoot?.());
|
|
15424
|
+
internal.unregisterRoot = void 0;
|
|
15425
|
+
attempt(() => detachRootExtensions(root.store));
|
|
15426
|
+
attempt(() => internal.unregisterPrimary?.());
|
|
15427
|
+
attempt(() => internal.untrackStandalone?.());
|
|
15428
|
+
attempt(() => state.events.disconnect?.());
|
|
15429
|
+
if (!internal.isSecondary && internal.actualRenderer?.xr && state.xr) attempt(() => state.xr.disconnect());
|
|
15430
|
+
attempt(() => cleanupHelperGroup(root.store));
|
|
15431
|
+
if (state.scene) attempt(() => dispose(state.scene));
|
|
15432
|
+
const canvasTarget = internal.canvasTarget;
|
|
15433
|
+
if (internal.isSecondary && canvasTarget?.dispose) attempt(() => canvasTarget.dispose());
|
|
15434
|
+
const released = attempt(() => internal.releaseRenderer?.());
|
|
15435
|
+
internal.releaseRenderer = void 0;
|
|
15436
|
+
if (callback) {
|
|
15437
|
+
if (released) {
|
|
15438
|
+
released.then(() => callback(canvas)).catch((error) => console.warn("[R3F] Error in unmount callback", error));
|
|
15439
|
+
} else {
|
|
15440
|
+
callback(canvas);
|
|
15441
|
+
}
|
|
15442
|
+
}
|
|
15443
|
+
}
|
|
15444
|
+
}
|
|
15445
|
+
|
|
15446
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
15447
|
+
const isConstructor = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
15448
|
+
function getLoader(Proto) {
|
|
15449
|
+
if (isConstructor(Proto)) {
|
|
15450
|
+
let loader = memoizedLoaders.get(Proto);
|
|
15451
|
+
if (!loader) {
|
|
15452
|
+
loader = new Proto();
|
|
15453
|
+
memoizedLoaders.set(Proto, loader);
|
|
15454
|
+
}
|
|
15455
|
+
return loader;
|
|
15456
|
+
}
|
|
15457
|
+
return Proto;
|
|
15458
|
+
}
|
|
15459
|
+
function loadingFn(extensions, onProgress) {
|
|
15460
|
+
return function(Proto, input) {
|
|
15461
|
+
const loader = getLoader(Proto);
|
|
15462
|
+
if (extensions) extensions(loader);
|
|
15463
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
15464
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
15465
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
15466
|
+
return data;
|
|
15467
|
+
});
|
|
15468
|
+
}
|
|
15469
|
+
return new Promise(
|
|
15470
|
+
(res, reject) => loader.load(
|
|
15471
|
+
input,
|
|
15472
|
+
(data) => {
|
|
15473
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
15474
|
+
res(data);
|
|
15475
|
+
},
|
|
15476
|
+
onProgress,
|
|
15477
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
15478
|
+
)
|
|
15479
|
+
);
|
|
15480
|
+
};
|
|
15481
|
+
}
|
|
15482
|
+
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
15483
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
15484
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
15485
|
+
const fn = loadingFn(extensions, onProgress);
|
|
15486
|
+
const results = cacheKeys.map(
|
|
15487
|
+
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
15488
|
+
);
|
|
15489
|
+
const stableRef = useRef(null);
|
|
15490
|
+
const previous = stableRef.current;
|
|
15491
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
15492
|
+
stableRef.current = stable;
|
|
15493
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
15494
|
+
}
|
|
15495
|
+
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
15496
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
15497
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
15498
|
+
cacheKeys.forEach(
|
|
15499
|
+
(key, index) => preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
15500
|
+
);
|
|
15501
|
+
};
|
|
15502
|
+
useLoader.clear = function(loader, input, cacheKey) {
|
|
15503
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
15504
|
+
cacheKeys.forEach((key) => clear([loader, key]));
|
|
15505
|
+
};
|
|
15506
|
+
useLoader.loader = getLoader;
|
|
15507
|
+
|
|
15508
|
+
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
15509
|
+
function getUrls(input) {
|
|
15510
|
+
if (typeof input === "string") return [input];
|
|
15511
|
+
if (Array.isArray(input)) return input;
|
|
15512
|
+
return Object.values(input);
|
|
15513
|
+
}
|
|
15514
|
+
function inputSignature(input) {
|
|
15515
|
+
if (typeof input === "string") return input;
|
|
15516
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
15517
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
15518
|
+
}
|
|
15519
|
+
function allUrlsCached(urls, textureCache) {
|
|
15520
|
+
return urls.every((url) => textureCache.has(url));
|
|
15521
|
+
}
|
|
15522
|
+
function buildFromCache(input, textureCache) {
|
|
15523
|
+
if (typeof input === "string") {
|
|
15524
|
+
return textureCache.get(input);
|
|
15525
|
+
} else if (Array.isArray(input)) {
|
|
15526
|
+
return input.map((url) => textureCache.get(url));
|
|
15527
|
+
} else {
|
|
15528
|
+
const result = {};
|
|
15529
|
+
const objInput = input;
|
|
15530
|
+
for (const key in objInput) {
|
|
15531
|
+
result[key] = textureCache.get(objInput[key]);
|
|
15532
|
+
}
|
|
15533
|
+
return result;
|
|
15534
|
+
}
|
|
15535
|
+
}
|
|
15536
|
+
function useTexture(input, optionsOrOnLoad) {
|
|
15537
|
+
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
15538
|
+
const store = useStore();
|
|
15539
|
+
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
15540
|
+
const { onLoad, cache = true } = options;
|
|
15541
|
+
const onLoadRef = useRef(onLoad);
|
|
15542
|
+
onLoadRef.current = onLoad;
|
|
15543
|
+
const onLoadCalledForRef = useRef(null);
|
|
15544
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
15545
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
15546
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
15547
|
+
const cachedResult = useMemo(() => {
|
|
15548
|
+
if (!cache) return null;
|
|
15549
|
+
const textures = store.getState().textures;
|
|
15550
|
+
if (!allUrlsCached(urls, textures)) return null;
|
|
15551
|
+
return buildFromCache(stableInput, textures);
|
|
15552
|
+
}, [cache, urls, stableInput, store]);
|
|
15553
|
+
const loadedTextures = useLoader(
|
|
15554
|
+
getThree().TextureLoader,
|
|
15555
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
15556
|
+
);
|
|
15557
|
+
const mappedTextures = useMemo(() => {
|
|
15558
|
+
if (cachedResult) return cachedResult;
|
|
15559
|
+
if (IsObject(stableInput)) {
|
|
15560
|
+
const keyed = {};
|
|
15561
|
+
const textureArray = loadedTextures;
|
|
15562
|
+
let i = 0;
|
|
15563
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
15564
|
+
return keyed;
|
|
15565
|
+
} else {
|
|
15566
|
+
return loadedTextures;
|
|
15567
|
+
}
|
|
15568
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
15569
|
+
useLayoutEffect(() => {
|
|
15570
|
+
if (cachedResult) return;
|
|
15571
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
15572
|
+
onLoadCalledForRef.current = inputKey;
|
|
15573
|
+
onLoadRef.current?.(mappedTextures);
|
|
15574
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
15575
|
+
useEffect(() => {
|
|
15576
|
+
if (cachedResult) return;
|
|
15577
|
+
if ("initTexture" in renderer) {
|
|
15578
|
+
let textureArray = [];
|
|
15579
|
+
if (Array.isArray(loadedTextures)) {
|
|
15580
|
+
textureArray = loadedTextures;
|
|
15581
|
+
} else if (loadedTextures.isTexture) {
|
|
15582
|
+
textureArray = [loadedTextures];
|
|
15583
|
+
} else if (IsObject(loadedTextures)) {
|
|
15584
|
+
textureArray = Object.values(loadedTextures);
|
|
14913
15585
|
}
|
|
14914
|
-
|
|
14915
|
-
if (
|
|
14916
|
-
|
|
14917
|
-
const support = wantsGL ? await webgl() : await webgpu();
|
|
14918
|
-
registerThree(support.three);
|
|
14919
|
-
state.internal.support = support;
|
|
14920
|
-
ensureStoreThreeObjects(store);
|
|
14921
|
-
if (support.kind === "webgl") {
|
|
14922
|
-
renderer = await resolveRenderer(glConfig, defaultGLProps, support.Renderer);
|
|
14923
|
-
state.internal.actualRenderer = renderer;
|
|
14924
|
-
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
14925
|
-
} else if (primaryCanvas) {
|
|
14926
|
-
const primary = await waitForPrimary(primaryCanvas);
|
|
14927
|
-
renderer = primary.renderer;
|
|
14928
|
-
state.internal.actualRenderer = renderer;
|
|
14929
|
-
const canvasTarget = new support.CanvasTarget(canvas);
|
|
14930
|
-
primary.store.setState((prev) => ({
|
|
14931
|
-
internal: { ...prev.internal, isMultiCanvas: true }
|
|
14932
|
-
}));
|
|
14933
|
-
state.set((prev) => ({
|
|
14934
|
-
webGPUSupported: primary.store.getState().webGPUSupported,
|
|
14935
|
-
renderer,
|
|
14936
|
-
primaryStore: primary.store,
|
|
14937
|
-
internal: {
|
|
14938
|
-
...prev.internal,
|
|
14939
|
-
canvasTarget,
|
|
14940
|
-
isMultiCanvas: true,
|
|
14941
|
-
isSecondary: true,
|
|
14942
|
-
targetId: primaryCanvas
|
|
14943
|
-
}
|
|
14944
|
-
}));
|
|
14945
|
-
} else {
|
|
14946
|
-
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer);
|
|
14947
|
-
if (!renderer.hasInitialized?.()) {
|
|
14948
|
-
const size2 = computeInitialSize(canvas, propsSize);
|
|
14949
|
-
if (size2.width > 0 && size2.height > 0) {
|
|
14950
|
-
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14951
|
-
renderer.setSize(size2.width, size2.height, false);
|
|
14952
|
-
}
|
|
14953
|
-
await renderer.init();
|
|
14954
|
-
}
|
|
14955
|
-
const backend = renderer.backend;
|
|
14956
|
-
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
14957
|
-
state.internal.actualRenderer = renderer;
|
|
14958
|
-
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14959
|
-
if (canvasId && !state.internal.isSecondary) {
|
|
14960
|
-
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14961
|
-
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14962
|
-
state.set((prev) => ({
|
|
14963
|
-
internal: {
|
|
14964
|
-
...prev.internal,
|
|
14965
|
-
canvasTarget,
|
|
14966
|
-
unregisterPrimary
|
|
14967
|
-
}
|
|
14968
|
-
}));
|
|
14969
|
-
}
|
|
14970
|
-
}
|
|
14971
|
-
})().catch((err) => {
|
|
14972
|
-
rendererSetup = null;
|
|
14973
|
-
throw err;
|
|
14974
|
-
});
|
|
15586
|
+
textureArray.forEach((texture) => {
|
|
15587
|
+
if (texture?.isTexture) {
|
|
15588
|
+
renderer.initTexture(texture);
|
|
14975
15589
|
}
|
|
14976
|
-
|
|
14977
|
-
|
|
14978
|
-
|
|
14979
|
-
|
|
14980
|
-
|
|
14981
|
-
|
|
14982
|
-
|
|
14983
|
-
const
|
|
14984
|
-
|
|
14985
|
-
|
|
14986
|
-
|
|
14987
|
-
|
|
14988
|
-
|
|
14989
|
-
|
|
14990
|
-
|
|
14991
|
-
const isCamera = cameraOptions?.isCamera;
|
|
14992
|
-
const camera = isCamera ? cameraOptions : orthographic ? new three.OrthographicCamera(0, 0, 0, 0, 0.1, 1e3) : new three.PerspectiveCamera(50, 0, 0.1, 1e3);
|
|
14993
|
-
if (!isCamera) {
|
|
14994
|
-
camera.position.z = 5;
|
|
14995
|
-
if (cameraOptions) {
|
|
14996
|
-
applyProps(camera, cameraOptions);
|
|
14997
|
-
if (!camera.manual) {
|
|
14998
|
-
const projectionProps = ["aspect", "left", "right", "bottom", "top"];
|
|
14999
|
-
if (projectionProps.some((prop) => prop in cameraOptions)) {
|
|
15000
|
-
camera.manual = true;
|
|
15001
|
-
camera.updateProjectionMatrix();
|
|
15002
|
-
}
|
|
15003
|
-
}
|
|
15590
|
+
});
|
|
15591
|
+
}
|
|
15592
|
+
}, [renderer, loadedTextures, cachedResult]);
|
|
15593
|
+
useEffect(() => {
|
|
15594
|
+
if (!cache) return;
|
|
15595
|
+
const urlTextureMap = urlTextureEntries(stableInput, mappedTextures);
|
|
15596
|
+
store.setState((state) => {
|
|
15597
|
+
const refs = new Map(state._textureRefs);
|
|
15598
|
+
let textures = state.textures;
|
|
15599
|
+
let added = false;
|
|
15600
|
+
for (const [url, texture] of urlTextureMap) {
|
|
15601
|
+
if (!textures.has(url)) {
|
|
15602
|
+
if (!added) {
|
|
15603
|
+
textures = new Map(textures);
|
|
15604
|
+
added = true;
|
|
15004
15605
|
}
|
|
15005
|
-
|
|
15606
|
+
textures.set(url, texture);
|
|
15006
15607
|
}
|
|
15007
|
-
|
|
15008
|
-
tempCamera = camera;
|
|
15009
|
-
raycaster.camera = camera;
|
|
15010
|
-
}
|
|
15011
|
-
if (!state.scene) {
|
|
15012
|
-
let scene;
|
|
15013
|
-
if (sceneOptions?.isScene) {
|
|
15014
|
-
scene = sceneOptions;
|
|
15015
|
-
prepare(scene, store, "", {});
|
|
15016
|
-
} else {
|
|
15017
|
-
scene = new three.Scene();
|
|
15018
|
-
prepare(scene, store, "", {});
|
|
15019
|
-
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
15020
|
-
}
|
|
15021
|
-
state.set((prev) => ({
|
|
15022
|
-
scene,
|
|
15023
|
-
rootScene: scene,
|
|
15024
|
-
internal: { ...prev.internal, container: scene }
|
|
15025
|
-
}));
|
|
15026
|
-
const camera = tempCamera;
|
|
15027
|
-
if (camera && !camera.parent) scene.add(camera);
|
|
15028
|
-
}
|
|
15029
|
-
if (events && !state.events.handlers) {
|
|
15030
|
-
state.set({ events: events(store) });
|
|
15031
|
-
let wasEnabled = true;
|
|
15032
|
-
store.subscribe((state2) => {
|
|
15033
|
-
const { enabled } = state2.events;
|
|
15034
|
-
if (enabled && !wasEnabled) {
|
|
15035
|
-
state2.events.update?.();
|
|
15036
|
-
}
|
|
15037
|
-
wasEnabled = enabled;
|
|
15038
|
-
});
|
|
15039
|
-
}
|
|
15040
|
-
if (_sizeProps !== void 0) {
|
|
15041
|
-
state.set({ _sizeProps });
|
|
15608
|
+
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
15042
15609
|
}
|
|
15043
|
-
|
|
15044
|
-
|
|
15610
|
+
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
15611
|
+
});
|
|
15612
|
+
unstageTextures(
|
|
15613
|
+
store,
|
|
15614
|
+
urlTextureMap.map(([url]) => url)
|
|
15615
|
+
);
|
|
15616
|
+
return () => store.setState((state) => {
|
|
15617
|
+
const refs = new Map(state._textureRefs);
|
|
15618
|
+
for (const [url] of urlTextureMap) {
|
|
15619
|
+
const next = (refs.get(url) ?? 0) - 1;
|
|
15620
|
+
if (next <= 0) refs.delete(url);
|
|
15621
|
+
else refs.set(url, next);
|
|
15045
15622
|
}
|
|
15046
|
-
|
|
15047
|
-
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
|
|
15057
|
-
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
|
|
15062
|
-
|
|
15063
|
-
|
|
15064
|
-
|
|
15065
|
-
|
|
15066
|
-
|
|
15067
|
-
|
|
15068
|
-
|
|
15069
|
-
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15088
|
-
|
|
15089
|
-
|
|
15090
|
-
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
state.set({ xr });
|
|
15101
|
-
}
|
|
15102
|
-
if (renderer.shadowMap && !is.equ(shadows, lastConfiguredProps.shadows, shallowLoose)) {
|
|
15103
|
-
lastConfiguredProps.shadows = shadows;
|
|
15104
|
-
const oldEnabled = renderer.shadowMap.enabled;
|
|
15105
|
-
const oldType = renderer.shadowMap.type;
|
|
15106
|
-
renderer.shadowMap.enabled = !!shadows;
|
|
15107
|
-
if (is.boo(shadows)) {
|
|
15108
|
-
renderer.shadowMap.type = three.PCFShadowMap;
|
|
15109
|
-
} else if (is.str(shadows)) {
|
|
15110
|
-
if (shadows === "soft") {
|
|
15111
|
-
notifyDepreciated({
|
|
15112
|
-
heading: 'shadows="soft" is deprecated',
|
|
15113
|
-
body: "Three has depreciated soft and improved basic PCFShadows, we converted for you.",
|
|
15114
|
-
link: "https://github.com/mrdoob/three.js/wiki/Migration-Guide?utm_source=chatgpt.com#181--182"
|
|
15115
|
-
});
|
|
15623
|
+
return { _textureRefs: refs };
|
|
15624
|
+
});
|
|
15625
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
15626
|
+
if (cache && !cachedResult) stageTextures(store, urlTextureEntries(stableInput, mappedTextures));
|
|
15627
|
+
return mappedTextures;
|
|
15628
|
+
}
|
|
15629
|
+
function urlTextureEntries(input, textures) {
|
|
15630
|
+
if (typeof input === "string") return [[input, textures]];
|
|
15631
|
+
if (Array.isArray(input)) return input.map((url, i) => [url, textures[i]]);
|
|
15632
|
+
const record = textures;
|
|
15633
|
+
return Object.keys(input).map((key) => [input[key], record[key]]);
|
|
15634
|
+
}
|
|
15635
|
+
useTexture.preload = (url) => {
|
|
15636
|
+
whenThree().then((three) => useLoader.preload(three.TextureLoader, url));
|
|
15637
|
+
};
|
|
15638
|
+
useTexture.clear = (input) => {
|
|
15639
|
+
if (hasThree()) useLoader.clear(getThree().TextureLoader, input);
|
|
15640
|
+
};
|
|
15641
|
+
const Texture = ({
|
|
15642
|
+
children,
|
|
15643
|
+
input,
|
|
15644
|
+
onLoad,
|
|
15645
|
+
cache
|
|
15646
|
+
}) => {
|
|
15647
|
+
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
15648
|
+
const ret = useTexture(input, options);
|
|
15649
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children?.(ret) });
|
|
15650
|
+
};
|
|
15651
|
+
|
|
15652
|
+
function useTextures(selector) {
|
|
15653
|
+
const store = useStore();
|
|
15654
|
+
const registry = useMemo(() => {
|
|
15655
|
+
const getState = store.getState;
|
|
15656
|
+
const setState = store.setState;
|
|
15657
|
+
const getOne = (key) => getState().textures.get(key);
|
|
15658
|
+
return {
|
|
15659
|
+
get all() {
|
|
15660
|
+
return getState().textures;
|
|
15661
|
+
},
|
|
15662
|
+
get(input) {
|
|
15663
|
+
if (typeof input === "string") return getOne(input);
|
|
15664
|
+
if (Array.isArray(input)) return input.map(getOne);
|
|
15665
|
+
const out = {};
|
|
15666
|
+
for (const name in input) out[name] = getOne(input[name]);
|
|
15667
|
+
return out;
|
|
15668
|
+
},
|
|
15669
|
+
has: (key) => getState().textures.has(key),
|
|
15670
|
+
add(keyOrRecord, texture) {
|
|
15671
|
+
setState((state) => {
|
|
15672
|
+
const textures = new Map(state.textures);
|
|
15673
|
+
if (typeof keyOrRecord === "string") {
|
|
15674
|
+
textures.set(keyOrRecord, texture);
|
|
15675
|
+
} else {
|
|
15676
|
+
for (const key in keyOrRecord) textures.set(key, keyOrRecord[key]);
|
|
15116
15677
|
}
|
|
15117
|
-
|
|
15118
|
-
basic: three.BasicShadowMap,
|
|
15119
|
-
percentage: three.PCFShadowMap,
|
|
15120
|
-
soft: three.PCFShadowMap,
|
|
15121
|
-
variance: three.VSMShadowMap
|
|
15122
|
-
};
|
|
15123
|
-
renderer.shadowMap.type = types[shadows] ?? three.PCFShadowMap;
|
|
15124
|
-
} else if (is.obj(shadows)) {
|
|
15125
|
-
Object.assign(renderer.shadowMap, shadows);
|
|
15126
|
-
}
|
|
15127
|
-
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
15128
|
-
renderer.shadowMap.needsUpdate = true;
|
|
15129
|
-
}
|
|
15130
|
-
}
|
|
15131
|
-
if (!configured) {
|
|
15132
|
-
renderer.outputColorSpace = three.SRGBColorSpace;
|
|
15133
|
-
renderer.toneMapping = three.ACESFilmicToneMapping;
|
|
15134
|
-
}
|
|
15135
|
-
const textureColorSpace = requestedTextureColorSpace ?? three.SRGBColorSpace;
|
|
15136
|
-
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
15137
|
-
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
15138
|
-
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
15139
|
-
}
|
|
15140
|
-
const r3fProps = ["textureColorSpace"];
|
|
15141
|
-
const constructorOnlyProps = ["samples", "antialias", "alpha", "canvas", "powerPreference"];
|
|
15142
|
-
const nonApplyProps = [...r3fProps, ...constructorOnlyProps];
|
|
15143
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
15144
|
-
const glProps = {};
|
|
15145
|
-
for (const key in glConfig) {
|
|
15146
|
-
if (!nonApplyProps.includes(key)) glProps[key] = glConfig[key];
|
|
15147
|
-
}
|
|
15148
|
-
applyProps(renderer, glProps);
|
|
15149
|
-
}
|
|
15150
|
-
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
15151
|
-
const currentRenderer = state.renderer;
|
|
15152
|
-
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
15153
|
-
const rendererProps = {};
|
|
15154
|
-
for (const key in rendererConfig) {
|
|
15155
|
-
if (!nonApplyProps.includes(key)) rendererProps[key] = rendererConfig[key];
|
|
15156
|
-
}
|
|
15157
|
-
applyProps(currentRenderer, rendererProps);
|
|
15158
|
-
}
|
|
15159
|
-
}
|
|
15160
|
-
const scheduler = getScheduler();
|
|
15161
|
-
const rootId = state.internal.rootId;
|
|
15162
|
-
if (!rootId) {
|
|
15163
|
-
const newRootId = canvasId || scheduler.generateRootId();
|
|
15164
|
-
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
15165
|
-
getState: () => store.getState(),
|
|
15166
|
-
onError: (err) => store.getState().setError(err),
|
|
15167
|
-
frameloop: store.getState().frameloop,
|
|
15168
|
-
before: schedulerConfig?.before,
|
|
15169
|
-
after: schedulerConfig?.after,
|
|
15170
|
-
order: schedulerConfig?.order
|
|
15678
|
+
return { textures };
|
|
15171
15679
|
});
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
renderer2.backend?.updateSize?.();
|
|
15182
|
-
}
|
|
15183
|
-
}
|
|
15184
|
-
},
|
|
15185
|
-
{
|
|
15186
|
-
id: `${newRootId}_canvasTarget`,
|
|
15187
|
-
rootId: newRootId,
|
|
15188
|
-
phase: "start",
|
|
15189
|
-
system: true
|
|
15190
|
-
}
|
|
15191
|
-
);
|
|
15192
|
-
const unregisterEventsFlush = scheduler.register(
|
|
15193
|
-
() => {
|
|
15194
|
-
const state2 = store.getState();
|
|
15195
|
-
state2.events.flush?.();
|
|
15196
|
-
},
|
|
15197
|
-
{
|
|
15198
|
-
id: `${newRootId}_events`,
|
|
15199
|
-
rootId: newRootId,
|
|
15200
|
-
phase: "input",
|
|
15201
|
-
system: true
|
|
15202
|
-
}
|
|
15203
|
-
);
|
|
15204
|
-
const unregisterFrustum = scheduler.register(
|
|
15205
|
-
() => {
|
|
15206
|
-
const state2 = store.getState();
|
|
15207
|
-
if (state2.autoUpdateFrustum && state2.camera) {
|
|
15208
|
-
updateFrustum(state2.camera, state2.frustum);
|
|
15209
|
-
}
|
|
15210
|
-
},
|
|
15211
|
-
{
|
|
15212
|
-
id: `${newRootId}_frustum`,
|
|
15213
|
-
rootId: newRootId,
|
|
15214
|
-
before: "render",
|
|
15215
|
-
system: true
|
|
15216
|
-
}
|
|
15217
|
-
);
|
|
15218
|
-
const unregisterVisibility = scheduler.register(
|
|
15219
|
-
() => {
|
|
15220
|
-
const state2 = store.getState();
|
|
15221
|
-
checkVisibility(state2);
|
|
15222
|
-
},
|
|
15223
|
-
{
|
|
15224
|
-
id: `${newRootId}_visibility`,
|
|
15225
|
-
rootId: newRootId,
|
|
15226
|
-
before: "render",
|
|
15227
|
-
system: true,
|
|
15228
|
-
after: `${newRootId}_frustum`
|
|
15229
|
-
}
|
|
15230
|
-
);
|
|
15231
|
-
const unregisterRender = scheduler.register(
|
|
15232
|
-
() => {
|
|
15233
|
-
const state2 = store.getState();
|
|
15234
|
-
const renderer2 = state2.internal.actualRenderer;
|
|
15235
|
-
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
15236
|
-
if (userHandlesRender || state2.internal.priority) return;
|
|
15237
|
-
try {
|
|
15238
|
-
const renderOverride = state2.internal.renderOverride;
|
|
15239
|
-
if (renderOverride) renderOverride();
|
|
15240
|
-
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
15241
|
-
} catch (error) {
|
|
15242
|
-
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
15243
|
-
}
|
|
15244
|
-
},
|
|
15245
|
-
{
|
|
15246
|
-
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
15247
|
-
id: canvasId || `${newRootId}_render`,
|
|
15248
|
-
rootId: newRootId,
|
|
15249
|
-
phase: "render",
|
|
15250
|
-
system: true,
|
|
15251
|
-
// Internal flag: this is a system job, not user-controlled
|
|
15252
|
-
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
15253
|
-
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
15254
|
-
}
|
|
15255
|
-
);
|
|
15256
|
-
state.set((state2) => ({
|
|
15257
|
-
internal: {
|
|
15258
|
-
...state2.internal,
|
|
15259
|
-
rootId: newRootId,
|
|
15260
|
-
unregisterRoot: () => {
|
|
15261
|
-
unregisterRoot();
|
|
15262
|
-
unregisterCanvasTarget();
|
|
15263
|
-
unregisterEventsFlush();
|
|
15264
|
-
unregisterFrustum();
|
|
15265
|
-
unregisterVisibility();
|
|
15266
|
-
unregisterRender();
|
|
15267
|
-
},
|
|
15268
|
-
scheduler
|
|
15269
|
-
}
|
|
15270
|
-
}));
|
|
15271
|
-
} else {
|
|
15272
|
-
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
15273
|
-
if (constraintsChanged) {
|
|
15274
|
-
scheduler.setRootConstraints(rootId, {
|
|
15275
|
-
before: schedulerConfig?.before,
|
|
15276
|
-
after: schedulerConfig?.after
|
|
15277
|
-
});
|
|
15278
|
-
}
|
|
15279
|
-
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
15280
|
-
scheduler.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
15680
|
+
},
|
|
15681
|
+
dispose(key, options) {
|
|
15682
|
+
const state = getState();
|
|
15683
|
+
const refs = state._textureRefs.get(key) ?? 0;
|
|
15684
|
+
if (refs > 0 && !options?.force) {
|
|
15685
|
+
console.warn(
|
|
15686
|
+
`[useTextures] "${key}" still has ${refs} active reference(s); skipping dispose. Pass { force: true } to override.`
|
|
15687
|
+
);
|
|
15688
|
+
return false;
|
|
15281
15689
|
}
|
|
15690
|
+
state.textures.get(key)?.dispose();
|
|
15691
|
+
setState((s) => {
|
|
15692
|
+
const textures = new Map(s.textures);
|
|
15693
|
+
textures.delete(key);
|
|
15694
|
+
const nextRefs = new Map(s._textureRefs);
|
|
15695
|
+
nextRefs.delete(key);
|
|
15696
|
+
return { textures, _textureRefs: nextRefs };
|
|
15697
|
+
});
|
|
15698
|
+
return true;
|
|
15699
|
+
},
|
|
15700
|
+
disposeAll() {
|
|
15701
|
+
for (const texture of getState().textures.values()) texture.dispose();
|
|
15702
|
+
setState({ textures: /* @__PURE__ */ new Map(), _textureRefs: /* @__PURE__ */ new Map() });
|
|
15282
15703
|
}
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
configured = true;
|
|
15289
|
-
resolve();
|
|
15290
|
-
return this;
|
|
15291
|
-
},
|
|
15292
|
-
render(children) {
|
|
15293
|
-
if (!configured && !pending) this.configure();
|
|
15294
|
-
pending.then(() => {
|
|
15295
|
-
reconciler.updateContainer(
|
|
15296
|
-
/* @__PURE__ */ jsx(Provider, { store, children, onCreated, rootElement: canvas }),
|
|
15297
|
-
fiber,
|
|
15298
|
-
null,
|
|
15299
|
-
() => void 0
|
|
15300
|
-
);
|
|
15301
|
-
});
|
|
15302
|
-
return store;
|
|
15303
|
-
},
|
|
15304
|
-
unmount() {
|
|
15305
|
-
unmountComponentAtNode(canvas);
|
|
15306
|
-
}
|
|
15307
|
-
};
|
|
15704
|
+
};
|
|
15705
|
+
}, [store]);
|
|
15706
|
+
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
15707
|
+
const selected = useThree(subscribe);
|
|
15708
|
+
return selector ? selected : registry;
|
|
15308
15709
|
}
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
|
|
15710
|
+
|
|
15711
|
+
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
15712
|
+
const support = useThree((s) => s.internal.support);
|
|
15713
|
+
const size = useThree((s) => s.size);
|
|
15714
|
+
let width;
|
|
15715
|
+
let height;
|
|
15716
|
+
let opts;
|
|
15717
|
+
if (typeof widthOrOptions === "object") {
|
|
15718
|
+
opts = widthOrOptions;
|
|
15719
|
+
} else if (typeof widthOrOptions === "number") {
|
|
15720
|
+
width = widthOrOptions;
|
|
15721
|
+
if (typeof heightOrOptions === "object") {
|
|
15722
|
+
height = widthOrOptions;
|
|
15723
|
+
opts = heightOrOptions;
|
|
15724
|
+
} else if (typeof heightOrOptions === "number") {
|
|
15725
|
+
height = heightOrOptions;
|
|
15726
|
+
opts = options;
|
|
15727
|
+
} else {
|
|
15728
|
+
height = widthOrOptions;
|
|
15729
|
+
}
|
|
15730
|
+
}
|
|
15731
|
+
return useMemo(() => {
|
|
15732
|
+
const w = width ?? size.width;
|
|
15733
|
+
const h = height ?? size.height;
|
|
15734
|
+
const Target = support.RenderTarget;
|
|
15735
|
+
return new Target(w, h, opts);
|
|
15736
|
+
}, [width, height, size.width, size.height, opts, support]);
|
|
15322
15737
|
}
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
|
|
15329
|
-
|
|
15330
|
-
|
|
15331
|
-
|
|
15332
|
-
|
|
15333
|
-
|
|
15738
|
+
|
|
15739
|
+
const presetsObj = {
|
|
15740
|
+
apartment: "lebombo_1k.hdr",
|
|
15741
|
+
city: "potsdamer_platz_1k.hdr",
|
|
15742
|
+
dawn: "kiara_1_dawn_1k.hdr",
|
|
15743
|
+
forest: "forest_slope_1k.hdr",
|
|
15744
|
+
lobby: "st_fagans_interior_1k.hdr",
|
|
15745
|
+
night: "dikhololo_night_1k.hdr",
|
|
15746
|
+
park: "rooitou_park_1k.hdr",
|
|
15747
|
+
studio: "studio_small_03_1k.hdr",
|
|
15748
|
+
sunset: "venice_sunset_1k.hdr",
|
|
15749
|
+
warehouse: "empty_warehouse_01_1k.hdr"
|
|
15750
|
+
};
|
|
15751
|
+
|
|
15752
|
+
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
15753
|
+
const isArray = (arr) => Array.isArray(arr);
|
|
15754
|
+
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
15755
|
+
const loadedLoaders = /* @__PURE__ */ new Map();
|
|
15756
|
+
const pendingLoaders = /* @__PURE__ */ new Map();
|
|
15757
|
+
function loadLoader(format) {
|
|
15758
|
+
let pending = pendingLoaders.get(format);
|
|
15759
|
+
if (!pending) {
|
|
15760
|
+
pending = importLoader(format).then(
|
|
15761
|
+
(loader) => {
|
|
15762
|
+
loadedLoaders.set(format, loader);
|
|
15763
|
+
return loader;
|
|
15764
|
+
},
|
|
15765
|
+
(error) => {
|
|
15766
|
+
pendingLoaders.delete(format);
|
|
15767
|
+
throw error;
|
|
15334
15768
|
}
|
|
15769
|
+
);
|
|
15770
|
+
pendingLoaders.set(format, pending);
|
|
15771
|
+
}
|
|
15772
|
+
return pending;
|
|
15773
|
+
}
|
|
15774
|
+
async function importLoader(format) {
|
|
15775
|
+
let loader;
|
|
15776
|
+
switch (format) {
|
|
15777
|
+
case "cube":
|
|
15778
|
+
loader = getThree().CubeTextureLoader;
|
|
15779
|
+
break;
|
|
15780
|
+
case "hdr-cube":
|
|
15781
|
+
loader = (await import('three/examples/jsm/loaders/HDRCubeTextureLoader.js')).HDRCubeTextureLoader;
|
|
15782
|
+
break;
|
|
15783
|
+
case "hdr":
|
|
15784
|
+
loader = (await import('three/examples/jsm/loaders/HDRLoader.js')).HDRLoader;
|
|
15785
|
+
break;
|
|
15786
|
+
case "exr":
|
|
15787
|
+
loader = (await import('three/examples/jsm/loaders/EXRLoader.js')).EXRLoader;
|
|
15788
|
+
break;
|
|
15789
|
+
case "jpg":
|
|
15790
|
+
loader = (await import('three/examples/jsm/loaders/UltraHDRLoader.js')).UltraHDRLoader;
|
|
15791
|
+
break;
|
|
15792
|
+
}
|
|
15793
|
+
return loader;
|
|
15794
|
+
}
|
|
15795
|
+
const LOADER_KEY = Symbol("r3f-environment-loader");
|
|
15796
|
+
function useEnvironmentLoader(format) {
|
|
15797
|
+
return suspend(() => loadLoader(format), [LOADER_KEY, format]);
|
|
15798
|
+
}
|
|
15799
|
+
function useEnvironment({
|
|
15800
|
+
files = defaultFiles,
|
|
15801
|
+
path = "",
|
|
15802
|
+
preset = void 0,
|
|
15803
|
+
colorSpace = void 0,
|
|
15804
|
+
extensions
|
|
15805
|
+
} = {}) {
|
|
15806
|
+
if (preset) {
|
|
15807
|
+
validatePreset(preset);
|
|
15808
|
+
files = presetsObj[preset];
|
|
15809
|
+
path = CUBEMAP_ROOT;
|
|
15810
|
+
}
|
|
15811
|
+
const multiFile = isArray(files);
|
|
15812
|
+
const { format, isCubemap } = getFormat(files);
|
|
15813
|
+
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
15814
|
+
const loader = useEnvironmentLoader(format);
|
|
15815
|
+
const loaderResult = useLoader(
|
|
15816
|
+
loader,
|
|
15817
|
+
multiFile ? [files] : files,
|
|
15818
|
+
(loader2) => {
|
|
15819
|
+
loader2.setPath?.(path);
|
|
15820
|
+
if (extensions) extensions(loader2);
|
|
15335
15821
|
}
|
|
15336
|
-
|
|
15337
|
-
|
|
15338
|
-
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
|
|
15348
|
-
|
|
15349
|
-
|
|
15350
|
-
|
|
15351
|
-
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
|
|
15822
|
+
);
|
|
15823
|
+
const texture = multiFile ? (
|
|
15824
|
+
// @ts-ignore
|
|
15825
|
+
loaderResult[0]
|
|
15826
|
+
) : loaderResult;
|
|
15827
|
+
const three = getThree();
|
|
15828
|
+
texture.mapping = isCubemap ? three.CubeReflectionMapping : three.EquirectangularReflectionMapping;
|
|
15829
|
+
texture.colorSpace = colorSpace ?? (isCubemap && format !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
15830
|
+
return texture;
|
|
15831
|
+
}
|
|
15832
|
+
const preloadDefaultOptions = {
|
|
15833
|
+
files: defaultFiles,
|
|
15834
|
+
path: "",
|
|
15835
|
+
preset: void 0,
|
|
15836
|
+
extensions: void 0
|
|
15837
|
+
};
|
|
15838
|
+
useEnvironment.preload = (preloadOptions) => {
|
|
15839
|
+
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
15840
|
+
let { files, path = "" } = options;
|
|
15841
|
+
const { preset, extensions } = options;
|
|
15842
|
+
if (preset) {
|
|
15843
|
+
validatePreset(preset);
|
|
15844
|
+
files = presetsObj[preset];
|
|
15845
|
+
path = CUBEMAP_ROOT;
|
|
15846
|
+
}
|
|
15847
|
+
const { format } = getFormat(files);
|
|
15848
|
+
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
15849
|
+
const input = isArray(files) ? [files] : files;
|
|
15850
|
+
loadLoader(format).then((loader) => {
|
|
15851
|
+
useLoader.preload(loader, input, (loader2) => {
|
|
15852
|
+
loader2.setPath?.(path);
|
|
15853
|
+
if (extensions) extensions(loader2);
|
|
15854
|
+
});
|
|
15855
|
+
});
|
|
15856
|
+
};
|
|
15857
|
+
const clearDefaultOptins = {
|
|
15858
|
+
files: defaultFiles,
|
|
15859
|
+
preset: void 0
|
|
15860
|
+
};
|
|
15861
|
+
useEnvironment.clear = (clearOptions) => {
|
|
15862
|
+
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
15863
|
+
let { files } = options;
|
|
15864
|
+
const { preset } = options;
|
|
15865
|
+
if (preset) {
|
|
15866
|
+
validatePreset(preset);
|
|
15867
|
+
files = presetsObj[preset];
|
|
15868
|
+
}
|
|
15869
|
+
const { format } = getFormat(files);
|
|
15870
|
+
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
15871
|
+
const input = isArray(files) ? [files] : files;
|
|
15872
|
+
const clear = (loader2) => useLoader.clear(loader2, input);
|
|
15873
|
+
const loader = loadedLoaders.get(format);
|
|
15874
|
+
if (loader) {
|
|
15875
|
+
clear(loader);
|
|
15876
|
+
} else {
|
|
15877
|
+
const pending = pendingLoaders.get(format);
|
|
15878
|
+
if (pending) void pending.then(clear, () => {
|
|
15364
15879
|
});
|
|
15365
15880
|
}
|
|
15881
|
+
};
|
|
15882
|
+
function validatePreset(preset) {
|
|
15883
|
+
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
15884
|
+
}
|
|
15885
|
+
function getFormat(files) {
|
|
15886
|
+
const isCubemap = isArray(files) && files.length === 6;
|
|
15887
|
+
const firstEntry = isArray(files) ? files[0] : files;
|
|
15888
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
15889
|
+
let format;
|
|
15890
|
+
if (isCubemap) format = firstExtension === "hdr" ? "hdr-cube" : "cube";
|
|
15891
|
+
else if (firstEntry.startsWith("data:application/exr")) format = "exr";
|
|
15892
|
+
else if (firstEntry.startsWith("data:application/hdr")) format = "hdr";
|
|
15893
|
+
else if (firstEntry.startsWith("data:image/jpeg")) format = "jpg";
|
|
15894
|
+
else if (firstExtension === "hdr" || firstExtension === "exr") format = firstExtension;
|
|
15895
|
+
else if (firstExtension === "jpg" || firstExtension === "jpeg") format = "jpg";
|
|
15896
|
+
return { format, isCubemap };
|
|
15897
|
+
}
|
|
15898
|
+
|
|
15899
|
+
function useInstanceHandle(ref) {
|
|
15900
|
+
const instance = useRef(null);
|
|
15901
|
+
useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
15902
|
+
return instance;
|
|
15903
|
+
}
|
|
15904
|
+
function useGraph(object) {
|
|
15905
|
+
return useMemo(() => buildGraph(object), [object]);
|
|
15366
15906
|
}
|
|
15907
|
+
|
|
15367
15908
|
function createPortal(children, container, state) {
|
|
15368
15909
|
return /* @__PURE__ */ jsx(Portal, { children, container, state });
|
|
15369
15910
|
}
|
|
@@ -15400,16 +15941,13 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
15400
15941
|
const [portalScene] = useState(() => {
|
|
15401
15942
|
if ("isScene" in container && container.isScene) return container;
|
|
15402
15943
|
if (!injectScene) return container;
|
|
15403
|
-
|
|
15404
|
-
container.add(scene);
|
|
15405
|
-
return scene;
|
|
15944
|
+
return new (getThree()).Scene();
|
|
15406
15945
|
});
|
|
15407
15946
|
useIsomorphicLayoutEffect(() => {
|
|
15947
|
+
if (portalScene === container || !injectScene) return;
|
|
15948
|
+
container.add(portalScene);
|
|
15408
15949
|
return () => {
|
|
15409
|
-
|
|
15410
|
-
container.remove(portalScene);
|
|
15411
|
-
dispose(portalScene);
|
|
15412
|
-
}
|
|
15950
|
+
container.remove(portalScene);
|
|
15413
15951
|
};
|
|
15414
15952
|
}, [portalScene, container, injectScene]);
|
|
15415
15953
|
const lastRootState = useRef(null);
|
|
@@ -15478,9 +16016,6 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
15478
16016
|
) })
|
|
15479
16017
|
);
|
|
15480
16018
|
}
|
|
15481
|
-
function flushSync(fn) {
|
|
15482
|
-
return reconciler.flushSyncFromReconciler(fn);
|
|
15483
|
-
}
|
|
15484
16019
|
|
|
15485
16020
|
const isRef = (obj) => obj.current && obj.current.isScene;
|
|
15486
16021
|
const resolveScene = (scene) => isRef(scene) ? scene.current : scene;
|
|
@@ -15716,19 +16251,6 @@ function parseBackground(background) {
|
|
|
15716
16251
|
return null;
|
|
15717
16252
|
}
|
|
15718
16253
|
|
|
15719
|
-
function parseRendererConfig(rendererProp) {
|
|
15720
|
-
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
15721
|
-
if (isRendererConfig) {
|
|
15722
|
-
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
15723
|
-
return {
|
|
15724
|
-
primaryCanvas: pc,
|
|
15725
|
-
scheduler: sc,
|
|
15726
|
-
renderer: Object.keys(rest).length > 0 ? rest : rendererProp
|
|
15727
|
-
};
|
|
15728
|
-
}
|
|
15729
|
-
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
15730
|
-
}
|
|
15731
|
-
|
|
15732
16254
|
function CanvasImpl({
|
|
15733
16255
|
ref,
|
|
15734
16256
|
children,
|
|
@@ -15737,11 +16259,13 @@ function CanvasImpl({
|
|
|
15737
16259
|
style,
|
|
15738
16260
|
id,
|
|
15739
16261
|
gl,
|
|
15740
|
-
renderer
|
|
16262
|
+
renderer,
|
|
16263
|
+
primary,
|
|
16264
|
+
share,
|
|
16265
|
+
scheduler,
|
|
15741
16266
|
events = createPointerEvents,
|
|
15742
16267
|
eventSource,
|
|
15743
16268
|
eventPrefix,
|
|
15744
|
-
shadows,
|
|
15745
16269
|
orthographic,
|
|
15746
16270
|
frameloop,
|
|
15747
16271
|
dpr,
|
|
@@ -15763,7 +16287,11 @@ function CanvasImpl({
|
|
|
15763
16287
|
provider,
|
|
15764
16288
|
...props
|
|
15765
16289
|
}) {
|
|
15766
|
-
const {
|
|
16290
|
+
const {
|
|
16291
|
+
shadows: removedShadows,
|
|
16292
|
+
primaryCanvas: removedPrimaryCanvas,
|
|
16293
|
+
...divProps
|
|
16294
|
+
} = props;
|
|
15767
16295
|
const Bridge = useBridge();
|
|
15768
16296
|
const backgroundProps = React.useMemo(() => parseBackground(background), [background]);
|
|
15769
16297
|
const [hasInitialSize, setHasInitialSize] = React.useState(false);
|
|
@@ -15809,10 +16337,22 @@ function CanvasImpl({
|
|
|
15809
16337
|
if (block) throw block;
|
|
15810
16338
|
if (error) throw error;
|
|
15811
16339
|
const root = React.useRef(null);
|
|
15812
|
-
const
|
|
15813
|
-
const
|
|
16340
|
+
const [gate, waitFor] = useGate();
|
|
16341
|
+
const rootState = React.useRef(null);
|
|
16342
|
+
const eventTarget = () => eventSource ? isRef$1(eventSource) ? eventSource.current : eventSource : divRef.current;
|
|
16343
|
+
const pointerMissed = React.useCallback(
|
|
16344
|
+
(...args) => handlePointerMissed.current?.(...args),
|
|
16345
|
+
[handlePointerMissed]
|
|
16346
|
+
);
|
|
16347
|
+
const dragOverMissed = React.useCallback(
|
|
16348
|
+
(...args) => handleDragOverMissed.current?.(...args),
|
|
16349
|
+
[handleDragOverMissed]
|
|
16350
|
+
);
|
|
16351
|
+
const dropMissed = React.useCallback(
|
|
16352
|
+
(...args) => handleDropMissed.current?.(...args),
|
|
16353
|
+
[handleDropMissed]
|
|
16354
|
+
);
|
|
15814
16355
|
useIsomorphicLayoutEffect(() => {
|
|
15815
|
-
effectActiveRef.current = true;
|
|
15816
16356
|
if (fallbackVisible) return;
|
|
15817
16357
|
const canvas = canvasRef.current;
|
|
15818
16358
|
if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
|
|
@@ -15822,97 +16362,111 @@ function CanvasImpl({
|
|
|
15822
16362
|
message: "React Three Fiber v10 is in ALPHA - expect breaking changes",
|
|
15823
16363
|
link: "https://github.com/pmndrs/react-three-fiber/discussions"
|
|
15824
16364
|
});
|
|
15825
|
-
const rootEntry = _roots.get(canvas);
|
|
15826
|
-
if (rootEntry?.store) {
|
|
15827
|
-
if (unsubscribeErrorRef.current) unsubscribeErrorRef.current();
|
|
15828
|
-
unsubscribeErrorRef.current = rootEntry.store.subscribe((state) => {
|
|
15829
|
-
if (state.error && effectActiveRef.current) {
|
|
15830
|
-
setError(state.error);
|
|
15831
|
-
}
|
|
15832
|
-
});
|
|
15833
|
-
}
|
|
15834
16365
|
}
|
|
15835
|
-
|
|
15836
|
-
|
|
15837
|
-
|
|
15838
|
-
|
|
15839
|
-
|
|
15840
|
-
|
|
15841
|
-
|
|
15842
|
-
|
|
15843
|
-
|
|
15844
|
-
|
|
15845
|
-
|
|
15846
|
-
|
|
15847
|
-
|
|
15848
|
-
|
|
15849
|
-
|
|
15850
|
-
|
|
15851
|
-
|
|
15852
|
-
|
|
15853
|
-
|
|
15854
|
-
|
|
15855
|
-
|
|
15856
|
-
|
|
15857
|
-
|
|
15858
|
-
|
|
15859
|
-
|
|
15860
|
-
|
|
15861
|
-
|
|
15862
|
-
|
|
15863
|
-
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
|
|
15870
|
-
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
|
|
15875
|
-
}
|
|
15876
|
-
onCreated?.(state);
|
|
15877
|
-
}
|
|
15878
|
-
}).then(
|
|
15879
|
-
() => true,
|
|
15880
|
-
// Renderer setup failed (e.g. no WebGL/WebGPU support). The `fallback` prop lives
|
|
15881
|
-
// inside <canvas>, which browsers don't display, so surface it as visible DOM
|
|
15882
|
-
// instead; with no fallback, rethrow to an external error boundary. (#3757)
|
|
15883
|
-
(setupError) => {
|
|
15884
|
-
if (effectActiveRef.current) {
|
|
15885
|
-
if (fallback != null) setFallbackVisible(true);
|
|
15886
|
-
else setError(setupError);
|
|
15887
|
-
}
|
|
15888
|
-
return false;
|
|
16366
|
+
const current = root.current;
|
|
16367
|
+
current.configure({
|
|
16368
|
+
id,
|
|
16369
|
+
primary,
|
|
16370
|
+
share,
|
|
16371
|
+
scheduler,
|
|
16372
|
+
gl,
|
|
16373
|
+
renderer,
|
|
16374
|
+
scene,
|
|
16375
|
+
events,
|
|
16376
|
+
_primaryToken: primaryToken,
|
|
16377
|
+
...{ shadows: removedShadows, primaryCanvas: removedPrimaryCanvas },
|
|
16378
|
+
orthographic,
|
|
16379
|
+
frameloop,
|
|
16380
|
+
dpr,
|
|
16381
|
+
performance,
|
|
16382
|
+
raycaster,
|
|
16383
|
+
camera,
|
|
16384
|
+
autoUpdateFrustum,
|
|
16385
|
+
occlusion,
|
|
16386
|
+
size: effectiveSize,
|
|
16387
|
+
// Store size props for reset functionality
|
|
16388
|
+
_sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
|
|
16389
|
+
forceEven,
|
|
16390
|
+
// Pass mutable reference to onPointerMissed so it's free to update
|
|
16391
|
+
onPointerMissed: pointerMissed,
|
|
16392
|
+
onDragOverMissed: dragOverMissed,
|
|
16393
|
+
onDropMissed: dropMissed,
|
|
16394
|
+
onCreated: (state) => {
|
|
16395
|
+
rootState.current = state;
|
|
16396
|
+
state.events.connect?.(eventTarget() ?? divRef.current);
|
|
16397
|
+
if (eventPrefix) {
|
|
16398
|
+
state.setEvents({
|
|
16399
|
+
compute: (event, state2) => {
|
|
16400
|
+
const x = event[eventPrefix + "X"];
|
|
16401
|
+
const y = event[eventPrefix + "Y"];
|
|
16402
|
+
state2.pointer.set(x / state2.size.width * 2 - 1, -(y / state2.size.height) * 2 + 1);
|
|
16403
|
+
state2.raycaster.setFromCamera(state2.pointer, state2.camera);
|
|
16404
|
+
}
|
|
16405
|
+
});
|
|
15889
16406
|
}
|
|
15890
|
-
|
|
15891
|
-
|
|
15892
|
-
|
|
16407
|
+
onCreated?.(state);
|
|
16408
|
+
}
|
|
16409
|
+
}).catch((setupError) => {
|
|
16410
|
+
if (root.current !== current) return;
|
|
16411
|
+
if (fallback != null) setFallbackVisible(true);
|
|
16412
|
+
else setError(setupError);
|
|
16413
|
+
});
|
|
16414
|
+
if (current.ready.status === "fulfilled") {
|
|
16415
|
+
current.render(
|
|
15893
16416
|
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: [
|
|
15894
16417
|
backgroundProps && /* @__PURE__ */ jsx(Environment, { ...backgroundProps }),
|
|
15895
16418
|
children ?? null
|
|
15896
16419
|
] }) }) })
|
|
15897
16420
|
);
|
|
16421
|
+
} else if (current.ready.status === "pending") {
|
|
16422
|
+
waitFor(current.ready);
|
|
15898
16423
|
}
|
|
15899
|
-
run();
|
|
15900
16424
|
}
|
|
15901
|
-
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
|
|
16425
|
+
});
|
|
16426
|
+
useIsomorphicLayoutEffect(() => {
|
|
16427
|
+
const store = canvasRef.current && _roots.get(canvasRef.current)?.store;
|
|
16428
|
+
if (!store) return;
|
|
16429
|
+
const report = () => {
|
|
16430
|
+
const error2 = store.getState().error;
|
|
16431
|
+
if (error2) setError(error2);
|
|
15907
16432
|
};
|
|
16433
|
+
report();
|
|
16434
|
+
return store.subscribe(report);
|
|
16435
|
+
});
|
|
16436
|
+
React.useEffect(() => {
|
|
16437
|
+
const state = rootState.current?.get();
|
|
16438
|
+
const target = eventTarget();
|
|
16439
|
+
if (state && target && state.events.connected !== target) state.events.connect?.(target);
|
|
15908
16440
|
});
|
|
16441
|
+
const insertionMounted = React.useRef(false);
|
|
16442
|
+
const [primaryToken] = React.useState(() => ({}));
|
|
16443
|
+
const primaryKey = React.useRef(null);
|
|
16444
|
+
React.useInsertionEffect(() => {
|
|
16445
|
+
insertionMounted.current = true;
|
|
16446
|
+
if (primary && provider.webgpu) {
|
|
16447
|
+
primaryKey.current ?? (primaryKey.current = id || DEFAULT_PRIMARY);
|
|
16448
|
+
announcePrimary(primaryKey.current, primaryToken);
|
|
16449
|
+
}
|
|
16450
|
+
return () => {
|
|
16451
|
+
insertionMounted.current = false;
|
|
16452
|
+
if (primaryKey.current) markWithdrawing(primaryToken);
|
|
16453
|
+
queueMicrotask(() => {
|
|
16454
|
+
if (insertionMounted.current) return;
|
|
16455
|
+
if (primaryKey.current) withdrawPrimary(primaryKey.current, primaryToken);
|
|
16456
|
+
const current = root.current;
|
|
16457
|
+
root.current = null;
|
|
16458
|
+
current?.unmount();
|
|
16459
|
+
});
|
|
16460
|
+
};
|
|
16461
|
+
}, []);
|
|
15909
16462
|
React.useEffect(() => {
|
|
15910
16463
|
const canvas = canvasRef.current;
|
|
15911
16464
|
if (canvas) {
|
|
15912
16465
|
return () => {
|
|
15913
16466
|
if (canvas.isConnected) return;
|
|
15914
|
-
|
|
16467
|
+
const current = root.current;
|
|
15915
16468
|
root.current = null;
|
|
16469
|
+
current?.unmount();
|
|
15916
16470
|
};
|
|
15917
16471
|
}
|
|
15918
16472
|
}, []);
|
|
@@ -15939,7 +16493,7 @@ function CanvasImpl({
|
|
|
15939
16493
|
}
|
|
15940
16494
|
}, [hmr]);
|
|
15941
16495
|
const pointerEvents = eventSource ? "none" : "auto";
|
|
15942
|
-
return /* @__PURE__ */
|
|
16496
|
+
return /* @__PURE__ */ jsxs(
|
|
15943
16497
|
"div",
|
|
15944
16498
|
{
|
|
15945
16499
|
ref: divRef,
|
|
@@ -15951,21 +16505,24 @@ function CanvasImpl({
|
|
|
15951
16505
|
pointerEvents,
|
|
15952
16506
|
...style
|
|
15953
16507
|
},
|
|
15954
|
-
...
|
|
15955
|
-
children:
|
|
15956
|
-
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
|
|
15960
|
-
"canvas",
|
|
15961
|
-
|
|
15962
|
-
|
|
15963
|
-
|
|
15964
|
-
|
|
15965
|
-
|
|
15966
|
-
|
|
15967
|
-
|
|
15968
|
-
|
|
16508
|
+
...divProps,
|
|
16509
|
+
children: [
|
|
16510
|
+
fallbackVisible ? (
|
|
16511
|
+
// Renderer setup failed: render the fallback as visible DOM. Inside <canvas> (below)
|
|
16512
|
+
// it exists in the tree but browsers never paint it, which is the whole bug (#3757).
|
|
16513
|
+
fallback
|
|
16514
|
+
) : /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
16515
|
+
"canvas",
|
|
16516
|
+
{
|
|
16517
|
+
ref: canvasRef,
|
|
16518
|
+
id,
|
|
16519
|
+
className: "r3f-canvas",
|
|
16520
|
+
style: { display: "block", width: "100%", height: "100%" },
|
|
16521
|
+
children: fallback
|
|
16522
|
+
}
|
|
16523
|
+
) }),
|
|
16524
|
+
gate
|
|
16525
|
+
]
|
|
15969
16526
|
}
|
|
15970
16527
|
);
|
|
15971
16528
|
}
|
|
@@ -15973,4 +16530,4 @@ function Canvas(props) {
|
|
|
15973
16530
|
return /* @__PURE__ */ jsx(FiberProvider, { children: /* @__PURE__ */ jsx(CanvasImpl, { ...props }) });
|
|
15974
16531
|
}
|
|
15975
16532
|
|
|
15976
|
-
export {
|
|
16533
|
+
export { prepare as $, useGraph as A, useLoader as B, Canvas as C, useTexture as D, EnvironmentMap as E, useTextures as F, useRenderTarget as G, useEnvironment as H, IsObject as I, extend as J, reconciler as K, flushSync as L, unmountComponentAtNode as M, createPortal as N, calculateDpr as O, Portal as P, getUuidPrefix as Q, updateCamera as R, updateFrustum as S, Texture as T, REACT_INTERNAL_PROPS as U, findInitialRoot as V, getRootState as W, buildGraph as X, dispose as Y, getInstanceProps as Z, _roots as _, createPointerEvents as a, invalidateInstance as a0, RESERVED_PROPS as a1, resolve as a2, attach as a3, detach as a4, diffProps as a5, applyProps as a6, is as a7, isOrthographicCamera as a8, isRef$1 as a9, isColorRepresentation as aa, isObject3D as ab, isTexture as ac, isLayers as ad, isUniform as ae, isVectorLike as af, isCopyable as ag, hasConstructor as ah, FROM_REF as ai, fromRef as aj, isFromRef as ak, ONCE as al, once as am, isOnce as an, addEffect as b, createRoot as c, addAfterEffect as d, addTail as e, advance as f, isRenderer as g, getPrimary as h, invalidate as i, hasPrimary as j, getPrimaryIds as k, createStore as l, getThree as m, hasThree as n, whenThree as o, EnvironmentCube as p, EnvironmentPortal as q, registerPrimary as r, Environment as s, presetsObj as t, unregisterPrimary as u, swapInteractivity as v, waitForPrimary as w, removeInteractivity as x, createEvents as y, useInstanceHandle as z };
|