@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,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
const
|
|
4
|
+
const textureStaging = require('./fiber.CsZ092z_.cjs');
|
|
5
5
|
const React = require('react');
|
|
6
6
|
const useMeasure = require('react-use-measure');
|
|
7
7
|
const itsFine = require('its-fine');
|
|
@@ -25,8 +25,8 @@ function _interopNamespaceCompat(e) {
|
|
|
25
25
|
return n;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const React__default = /*#__PURE__*/_interopDefaultCompat(React);
|
|
29
28
|
const React__namespace = /*#__PURE__*/_interopNamespaceCompat(React);
|
|
29
|
+
const React__default = /*#__PURE__*/_interopDefaultCompat(React);
|
|
30
30
|
const useMeasure__default = /*#__PURE__*/_interopDefaultCompat(useMeasure);
|
|
31
31
|
const w1__default = /*#__PURE__*/_interopDefaultCompat(w1);
|
|
32
32
|
|
|
@@ -128,6 +128,20 @@ function updateFrustum(camera, frustum) {
|
|
|
128
128
|
target.setFromProjectionMatrix(frustumMatrix);
|
|
129
129
|
return target;
|
|
130
130
|
}
|
|
131
|
+
function computeInitialSize(canvas, size) {
|
|
132
|
+
if (!size && typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
133
|
+
const { width, height, top, left } = canvas.parentElement.getBoundingClientRect();
|
|
134
|
+
return { width, height, top, left };
|
|
135
|
+
} else if (!size && typeof OffscreenCanvas !== "undefined" && canvas instanceof OffscreenCanvas) {
|
|
136
|
+
return {
|
|
137
|
+
width: canvas.width,
|
|
138
|
+
height: canvas.height,
|
|
139
|
+
top: 0,
|
|
140
|
+
left: 0
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return { width: 0, height: 0, top: 0, left: 0, ...size };
|
|
144
|
+
}
|
|
131
145
|
|
|
132
146
|
const REACT_INTERNAL_PROPS = ["children", "key", "ref"];
|
|
133
147
|
function findInitialRoot(instance) {
|
|
@@ -195,6 +209,7 @@ function prepare(target, root, type, props) {
|
|
|
195
209
|
object,
|
|
196
210
|
eventCount: 0,
|
|
197
211
|
handlers: {},
|
|
212
|
+
previousVisible: void 0,
|
|
198
213
|
isHidden: false
|
|
199
214
|
};
|
|
200
215
|
if (object) object.__r3f = instance;
|
|
@@ -443,6 +458,28 @@ const VISIBILITY_EVENT_REGEX = /^on(Framed|Occluded|Visible)$/;
|
|
|
443
458
|
const INDEX_REGEX = /-\d+$/;
|
|
444
459
|
const MEMOIZED_PROTOTYPES = /* @__PURE__ */ new Map();
|
|
445
460
|
const colorMaps = ["map", "emissiveMap", "sheenColorMap", "specularColorMap", "envMap"];
|
|
461
|
+
const programProps = /* @__PURE__ */ new Set([
|
|
462
|
+
"transparent",
|
|
463
|
+
"vertexColors",
|
|
464
|
+
"flatShading",
|
|
465
|
+
"fog",
|
|
466
|
+
// Culling is live, but DOUBLE_SIDED / FLIP_SIDED normal flipping is compiled in
|
|
467
|
+
"side",
|
|
468
|
+
"alphaHash",
|
|
469
|
+
"premultipliedAlpha",
|
|
470
|
+
// Both feed the OPAQUE define when the material is not transparent
|
|
471
|
+
"blending",
|
|
472
|
+
"alphaToCoverage",
|
|
473
|
+
"dithering",
|
|
474
|
+
"sizeAttenuation",
|
|
475
|
+
"combine",
|
|
476
|
+
"normalMapType",
|
|
477
|
+
"depthPacking"
|
|
478
|
+
]);
|
|
479
|
+
function changesProgram(root, key, previous, next) {
|
|
480
|
+
if (!root?.isMaterial || previous === next) return false;
|
|
481
|
+
return programProps.has(key) || isTexture(previous) !== isTexture(next);
|
|
482
|
+
}
|
|
446
483
|
function resolve(root, key) {
|
|
447
484
|
if (!key.includes("-")) return { root, key, target: root[key] };
|
|
448
485
|
if (key in root) return { root, key, target: root[key] };
|
|
@@ -473,6 +510,7 @@ function attach(parent, child) {
|
|
|
473
510
|
const { root, key } = resolve(parent.object, child.props.attach);
|
|
474
511
|
child.previousAttach = root[key];
|
|
475
512
|
root[key] = child.object;
|
|
513
|
+
if (changesProgram(root, key, child.previousAttach, child.object)) root.needsUpdate = true;
|
|
476
514
|
} else if (is.fun(child.props.attach)) {
|
|
477
515
|
child.previousAttach = child.props.attach(parent.object, child.object);
|
|
478
516
|
}
|
|
@@ -483,6 +521,7 @@ function detach(parent, child) {
|
|
|
483
521
|
const previous = child.previousAttach;
|
|
484
522
|
if (previous === void 0) delete root[key];
|
|
485
523
|
else root[key] = previous;
|
|
524
|
+
if (changesProgram(root, key, child.object, previous)) root.needsUpdate = true;
|
|
486
525
|
} else {
|
|
487
526
|
child.previousAttach?.(parent.object, child.object);
|
|
488
527
|
}
|
|
@@ -527,7 +566,7 @@ function applyProps(object, props) {
|
|
|
527
566
|
const value = props[prop];
|
|
528
567
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
529
568
|
if (prop === "onUpdate") {
|
|
530
|
-
|
|
569
|
+
textureStaging.notifyDepreciated({
|
|
531
570
|
heading: "onUpdate is no longer an R3F prop",
|
|
532
571
|
body: "v10 removed the onUpdate hook: R3F no longer calls it after prop updates. The value is assigned to the object by name. On a Texture that sets three's Texture.onUpdate, which the renderer calls after a GPU upload, not after prop changes. On a node it replaces the Node.onUpdate() method. On other objects it is never called.\n\nUse an effect keyed on the props that change, read the object in useFrame, or use a ref callback.",
|
|
533
572
|
link: "https://docs.pmnd.rs/react-three-fiber/migration/v10#onupdate-removed"
|
|
@@ -562,6 +601,10 @@ function applyProps(object, props) {
|
|
|
562
601
|
}
|
|
563
602
|
continue;
|
|
564
603
|
}
|
|
604
|
+
if (prop === "visible" && instance?.isHidden && instance.previousVisible !== void 0) {
|
|
605
|
+
instance.previousVisible = value;
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
565
608
|
let { root, key, target } = resolve(object, prop);
|
|
566
609
|
if (target === void 0 && (typeof root !== "object" || root === null)) {
|
|
567
610
|
throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`);
|
|
@@ -597,9 +640,12 @@ function applyProps(object, props) {
|
|
|
597
640
|
}
|
|
598
641
|
} else {
|
|
599
642
|
if (key === "material") assertNodeMaterialSupported(rootState, value);
|
|
643
|
+
const previous = root[key];
|
|
600
644
|
root[key] = value;
|
|
601
645
|
if (key.endsWith("Node") && root.isMaterial) {
|
|
602
646
|
root.needsUpdate = true;
|
|
647
|
+
} else if (changesProgram(root, key, previous, value)) {
|
|
648
|
+
root.needsUpdate = true;
|
|
603
649
|
}
|
|
604
650
|
const three = rootState && getThree();
|
|
605
651
|
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
|
|
@@ -640,471 +686,428 @@ function applyProps(object, props) {
|
|
|
640
686
|
return object;
|
|
641
687
|
}
|
|
642
688
|
|
|
643
|
-
const
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
if (!loader) {
|
|
649
|
-
loader = new Proto();
|
|
650
|
-
memoizedLoaders.set(Proto, loader);
|
|
651
|
-
}
|
|
652
|
-
return loader;
|
|
653
|
-
}
|
|
654
|
-
return Proto;
|
|
655
|
-
}
|
|
656
|
-
function loadingFn(extensions, onProgress) {
|
|
657
|
-
return function(Proto, input) {
|
|
658
|
-
const loader = getLoader(Proto);
|
|
659
|
-
if (extensions) extensions(loader);
|
|
660
|
-
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
661
|
-
return loader.loadAsync(input, onProgress).then((data) => {
|
|
662
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
663
|
-
return data;
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
return new Promise(
|
|
667
|
-
(res, reject) => loader.load(
|
|
668
|
-
input,
|
|
669
|
-
(data) => {
|
|
670
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
671
|
-
res(data);
|
|
672
|
-
},
|
|
673
|
-
onProgress,
|
|
674
|
-
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
675
|
-
)
|
|
676
|
-
);
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
680
|
-
const inputs = Array.isArray(input) ? input : [input];
|
|
681
|
-
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
682
|
-
const fn = loadingFn(extensions, onProgress);
|
|
683
|
-
const results = cacheKeys.map(
|
|
684
|
-
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
685
|
-
);
|
|
686
|
-
const stableRef = React.useRef(null);
|
|
687
|
-
const previous = stableRef.current;
|
|
688
|
-
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
689
|
-
stableRef.current = stable;
|
|
690
|
-
return Array.isArray(input) ? stable : stable[0];
|
|
689
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
690
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
691
|
+
if (!stack) return false;
|
|
692
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
693
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
691
694
|
}
|
|
692
|
-
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
693
|
-
const inputs = Array.isArray(input) ? input : [input];
|
|
694
|
-
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
695
|
-
cacheKeys.forEach(
|
|
696
|
-
(key, index) => suspendReact.preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
697
|
-
);
|
|
698
|
-
};
|
|
699
|
-
useLoader.clear = function(loader, input, cacheKey) {
|
|
700
|
-
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
701
|
-
cacheKeys.forEach((key) => suspendReact.clear([loader, key]));
|
|
702
|
-
};
|
|
703
|
-
useLoader.loader = getLoader;
|
|
704
695
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
if (typeof input === "string") return input;
|
|
713
|
-
if (Array.isArray(input)) return input.join("\0");
|
|
714
|
-
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
715
|
-
}
|
|
716
|
-
function allUrlsCached(urls, textureCache) {
|
|
717
|
-
return urls.every((url) => textureCache.has(url));
|
|
696
|
+
function updateSize(state, size, imperative) {
|
|
697
|
+
state.set((current) => ({
|
|
698
|
+
size,
|
|
699
|
+
viewport: { ...current.viewport, ...current.viewport.getCurrentViewport(current.camera, void 0, size) },
|
|
700
|
+
_sizeImperative: imperative
|
|
701
|
+
}));
|
|
702
|
+
state.invalidate();
|
|
718
703
|
}
|
|
719
|
-
function
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
return input.map((url) => textureCache.get(url));
|
|
724
|
-
} else {
|
|
725
|
-
const result = {};
|
|
726
|
-
const objInput = input;
|
|
727
|
-
for (const key in objInput) {
|
|
728
|
-
result[key] = textureCache.get(objInput[key]);
|
|
729
|
-
}
|
|
730
|
-
return result;
|
|
731
|
-
}
|
|
704
|
+
function configureSize(store, size) {
|
|
705
|
+
const state = store.getState();
|
|
706
|
+
if (state._sizeImperative || is.equ(size, state.size, { objects: "shallow", strict: false })) return;
|
|
707
|
+
updateSize(state, size, false);
|
|
732
708
|
}
|
|
733
|
-
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
if (IsObject(stableInput)) {
|
|
757
|
-
const keyed = {};
|
|
758
|
-
const textureArray = loadedTextures;
|
|
759
|
-
let i = 0;
|
|
760
|
-
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
761
|
-
return keyed;
|
|
762
|
-
} else {
|
|
763
|
-
return loadedTextures;
|
|
764
|
-
}
|
|
765
|
-
}, [stableInput, loadedTextures, cachedResult]);
|
|
766
|
-
React.useLayoutEffect(() => {
|
|
767
|
-
if (cachedResult) return;
|
|
768
|
-
if (onLoadCalledForRef.current === inputKey) return;
|
|
769
|
-
onLoadCalledForRef.current = inputKey;
|
|
770
|
-
onLoadRef.current?.(mappedTextures);
|
|
771
|
-
}, [cachedResult, mappedTextures, inputKey]);
|
|
772
|
-
React.useEffect(() => {
|
|
773
|
-
if (cachedResult) return;
|
|
774
|
-
if ("initTexture" in renderer) {
|
|
775
|
-
let textureArray = [];
|
|
776
|
-
if (Array.isArray(loadedTextures)) {
|
|
777
|
-
textureArray = loadedTextures;
|
|
778
|
-
} else if (loadedTextures.isTexture) {
|
|
779
|
-
textureArray = [loadedTextures];
|
|
780
|
-
} else if (IsObject(loadedTextures)) {
|
|
781
|
-
textureArray = Object.values(loadedTextures);
|
|
709
|
+
const createStore = (invalidate, advance) => {
|
|
710
|
+
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
711
|
+
let position;
|
|
712
|
+
let defaultTarget;
|
|
713
|
+
let tempTarget;
|
|
714
|
+
function getCurrentViewport(camera = get().camera, target = void 0, size = get().size) {
|
|
715
|
+
const { Vector3 } = getThree();
|
|
716
|
+
position ?? (position = new Vector3());
|
|
717
|
+
defaultTarget ?? (defaultTarget = new Vector3());
|
|
718
|
+
tempTarget ?? (tempTarget = new Vector3());
|
|
719
|
+
target ?? (target = defaultTarget);
|
|
720
|
+
const { width, height, top, left } = size;
|
|
721
|
+
const aspect = width / height;
|
|
722
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
723
|
+
else tempTarget.set(...target);
|
|
724
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
725
|
+
if (isOrthographicCamera(camera)) {
|
|
726
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
727
|
+
} else {
|
|
728
|
+
const fov = camera.fov * Math.PI / 180;
|
|
729
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
730
|
+
const w = h * (width / height);
|
|
731
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
782
732
|
}
|
|
783
|
-
textureArray.forEach((texture) => {
|
|
784
|
-
if (texture?.isTexture) {
|
|
785
|
-
renderer.initTexture(texture);
|
|
786
|
-
}
|
|
787
|
-
});
|
|
788
733
|
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
734
|
+
let performanceTimeout = void 0;
|
|
735
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
736
|
+
const rootState = {
|
|
737
|
+
set,
|
|
738
|
+
get,
|
|
739
|
+
// Mock objects that have to be configured
|
|
740
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
741
|
+
primaryStore: null,
|
|
742
|
+
gl: null,
|
|
743
|
+
renderer: null,
|
|
744
|
+
camera: null,
|
|
745
|
+
// frustum, pointer and mouse are three objects; configure() creates them with the renderer
|
|
746
|
+
frustum: null,
|
|
747
|
+
autoUpdateFrustum: true,
|
|
748
|
+
raycaster: null,
|
|
749
|
+
events: {
|
|
750
|
+
priority: 1,
|
|
751
|
+
enabled: true,
|
|
752
|
+
connected: false,
|
|
753
|
+
frameTimedRaycasts: true,
|
|
754
|
+
alwaysFireOnScroll: true,
|
|
755
|
+
updateOnFrame: false
|
|
756
|
+
},
|
|
757
|
+
scene: null,
|
|
758
|
+
rootScene: null,
|
|
759
|
+
xr: null,
|
|
760
|
+
inspector: null,
|
|
761
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
762
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
763
|
+
textureColorSpace: "srgb",
|
|
764
|
+
// THREE.SRGBColorSpace
|
|
765
|
+
isLegacy: false,
|
|
766
|
+
webGPUSupported: false,
|
|
767
|
+
isNative: false,
|
|
768
|
+
controls: null,
|
|
769
|
+
pointer: null,
|
|
770
|
+
mouse: null,
|
|
771
|
+
frameloop: "always",
|
|
772
|
+
onPointerMissed: void 0,
|
|
773
|
+
onDragOverMissed: void 0,
|
|
774
|
+
onDropMissed: void 0,
|
|
775
|
+
performance: {
|
|
776
|
+
current: 1,
|
|
777
|
+
min: 0.5,
|
|
778
|
+
max: 1,
|
|
779
|
+
debounce: 200,
|
|
780
|
+
regress: () => {
|
|
781
|
+
const state2 = get();
|
|
782
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
783
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
784
|
+
performanceTimeout = setTimeout(
|
|
785
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
786
|
+
state2.performance.debounce
|
|
787
|
+
);
|
|
804
788
|
}
|
|
805
|
-
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
806
|
-
}
|
|
807
|
-
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
808
|
-
});
|
|
809
|
-
extensions.unstageTextures(
|
|
810
|
-
store,
|
|
811
|
-
urlTextureMap.map(([url]) => url)
|
|
812
|
-
);
|
|
813
|
-
return () => store.setState((state) => {
|
|
814
|
-
const refs = new Map(state._textureRefs);
|
|
815
|
-
for (const [url] of urlTextureMap) {
|
|
816
|
-
const next = (refs.get(url) ?? 0) - 1;
|
|
817
|
-
if (next <= 0) refs.delete(url);
|
|
818
|
-
else refs.set(url, next);
|
|
819
|
-
}
|
|
820
|
-
return { _textureRefs: refs };
|
|
821
|
-
});
|
|
822
|
-
}, [cache, stableInput, mappedTextures, store]);
|
|
823
|
-
if (cache && !cachedResult) extensions.stageTextures(store, urlTextureEntries(stableInput, mappedTextures));
|
|
824
|
-
return mappedTextures;
|
|
825
|
-
}
|
|
826
|
-
function urlTextureEntries(input, textures) {
|
|
827
|
-
if (typeof input === "string") return [[input, textures]];
|
|
828
|
-
if (Array.isArray(input)) return input.map((url, i) => [url, textures[i]]);
|
|
829
|
-
const record = textures;
|
|
830
|
-
return Object.keys(input).map((key) => [input[key], record[key]]);
|
|
831
|
-
}
|
|
832
|
-
useTexture.preload = (url) => {
|
|
833
|
-
whenThree().then((three) => useLoader.preload(three.TextureLoader, url));
|
|
834
|
-
};
|
|
835
|
-
useTexture.clear = (input) => {
|
|
836
|
-
if (hasThree()) useLoader.clear(getThree().TextureLoader, input);
|
|
837
|
-
};
|
|
838
|
-
const Texture = ({
|
|
839
|
-
children,
|
|
840
|
-
input,
|
|
841
|
-
onLoad,
|
|
842
|
-
cache
|
|
843
|
-
}) => {
|
|
844
|
-
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
845
|
-
const ret = useTexture(input, options);
|
|
846
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children?.(ret) });
|
|
847
|
-
};
|
|
848
|
-
|
|
849
|
-
function useTextures(selector) {
|
|
850
|
-
const store = extensions.useStore();
|
|
851
|
-
const registry = React.useMemo(() => {
|
|
852
|
-
const getState = store.getState;
|
|
853
|
-
const setState = store.setState;
|
|
854
|
-
const getOne = (key) => getState().textures.get(key);
|
|
855
|
-
return {
|
|
856
|
-
get all() {
|
|
857
|
-
return getState().textures;
|
|
858
789
|
},
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
790
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
791
|
+
viewport: {
|
|
792
|
+
initialDpr: 0,
|
|
793
|
+
dpr: 0,
|
|
794
|
+
width: 0,
|
|
795
|
+
height: 0,
|
|
796
|
+
top: 0,
|
|
797
|
+
left: 0,
|
|
798
|
+
aspect: 0,
|
|
799
|
+
distance: 0,
|
|
800
|
+
factor: 0,
|
|
801
|
+
getCurrentViewport
|
|
865
802
|
},
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
if (
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
803
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
804
|
+
setSize: (width, height, top, left) => {
|
|
805
|
+
const state2 = get();
|
|
806
|
+
if (width === void 0) {
|
|
807
|
+
if (state2._sizeProps) {
|
|
808
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
809
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
810
|
+
const currentSize = state2.size;
|
|
811
|
+
const newSize = {
|
|
812
|
+
width: propW ?? currentSize.width,
|
|
813
|
+
height: propH ?? currentSize.height,
|
|
814
|
+
top: currentSize.top,
|
|
815
|
+
left: currentSize.left
|
|
816
|
+
};
|
|
817
|
+
updateSize(state2, newSize, false);
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
874
820
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
},
|
|
878
|
-
dispose(key, options) {
|
|
879
|
-
const state = getState();
|
|
880
|
-
const refs = state._textureRefs.get(key) ?? 0;
|
|
881
|
-
if (refs > 0 && !options?.force) {
|
|
882
|
-
console.warn(
|
|
883
|
-
`[useTextures] "${key}" still has ${refs} active reference(s); skipping dispose. Pass { force: true } to override.`
|
|
884
|
-
);
|
|
885
|
-
return false;
|
|
821
|
+
set({ _sizeImperative: false });
|
|
822
|
+
return;
|
|
886
823
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
return { textures, _textureRefs: nextRefs };
|
|
894
|
-
});
|
|
895
|
-
return true;
|
|
824
|
+
const w = width;
|
|
825
|
+
const h = height ?? width;
|
|
826
|
+
const t = top ?? state2.size.top;
|
|
827
|
+
const l = left ?? state2.size.left;
|
|
828
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
829
|
+
updateSize(state2, size, true);
|
|
896
830
|
},
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
831
|
+
setDpr: (dpr) => set((state2) => {
|
|
832
|
+
const resolved = calculateDpr(dpr);
|
|
833
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
834
|
+
}),
|
|
835
|
+
setFrameloop: (frameloop = "always") => {
|
|
836
|
+
const rootId = get().internal.rootId;
|
|
837
|
+
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
838
|
+
set(() => ({ frameloop }));
|
|
839
|
+
},
|
|
840
|
+
setError: (error) => set(() => ({ error })),
|
|
841
|
+
error: null,
|
|
842
|
+
//* Texture registry (useTextures) ==============================
|
|
843
|
+
// TSL fields (uniforms, nodes, ..., renderPipeline) are added by @react-three/tsl's root extension.
|
|
844
|
+
textures: /* @__PURE__ */ new Map(),
|
|
845
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
846
|
+
_sizeImperative: false,
|
|
847
|
+
_sizeProps: null,
|
|
848
|
+
previousRoot: void 0,
|
|
849
|
+
internal: {
|
|
850
|
+
// Events
|
|
851
|
+
interaction: [],
|
|
852
|
+
subscribers: [],
|
|
853
|
+
// Per-pointer state (new unified structure)
|
|
854
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
855
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
856
|
+
lastEvent: React__namespace.createRef(),
|
|
857
|
+
// Deprecated but kept for backwards compatibility
|
|
858
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
859
|
+
initialClick: [0, 0],
|
|
860
|
+
initialHits: [],
|
|
861
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
862
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
863
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
864
|
+
// Occlusion system (WebGPU only)
|
|
865
|
+
occlusionEnabled: false,
|
|
866
|
+
occlusionObserver: null,
|
|
867
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
868
|
+
helperGroup: null,
|
|
869
|
+
// Updates
|
|
870
|
+
active: false,
|
|
871
|
+
frames: 0,
|
|
872
|
+
priority: 0,
|
|
873
|
+
subscribe: (ref, priority, store) => {
|
|
874
|
+
const internal = get().internal;
|
|
875
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
876
|
+
internal.subscribers.push({ ref, priority, store });
|
|
877
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
878
|
+
return () => {
|
|
879
|
+
const internal2 = get().internal;
|
|
880
|
+
if (internal2?.subscribers) {
|
|
881
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
882
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
},
|
|
886
|
+
// Renderer Storage (single source of truth)
|
|
887
|
+
actualRenderer: null,
|
|
888
|
+
// The renderer support configure() loads for this root
|
|
889
|
+
support: null,
|
|
890
|
+
// Scheduler for useFrameNext (initialized in loop.ts)
|
|
891
|
+
scheduler: null,
|
|
892
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
893
|
+
renderOverride: null
|
|
900
894
|
}
|
|
901
895
|
};
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
896
|
+
return rootState;
|
|
897
|
+
});
|
|
898
|
+
const state = rootStore.getState();
|
|
899
|
+
Object.defineProperty(state, "gl", {
|
|
900
|
+
get() {
|
|
901
|
+
const currentState = rootStore.getState();
|
|
902
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
903
|
+
const stack = new Error().stack || "";
|
|
904
|
+
if (!isInternalRendererAccess(stack)) {
|
|
905
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
906
|
+
textureStaging.notifyDepreciated({
|
|
907
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
908
|
+
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
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
return currentState.internal.actualRenderer;
|
|
913
|
+
},
|
|
914
|
+
set(value) {
|
|
915
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
916
|
+
},
|
|
917
|
+
enumerable: true,
|
|
918
|
+
configurable: true
|
|
919
|
+
});
|
|
920
|
+
Object.defineProperty(state, "renderer", {
|
|
921
|
+
get() {
|
|
922
|
+
return rootStore.getState().internal.actualRenderer;
|
|
923
|
+
},
|
|
924
|
+
set(value) {
|
|
925
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
926
|
+
},
|
|
927
|
+
enumerable: true,
|
|
928
|
+
configurable: true
|
|
929
|
+
});
|
|
930
|
+
let oldScene = state.scene;
|
|
931
|
+
rootStore.subscribe(() => {
|
|
932
|
+
const currentState = rootStore.getState();
|
|
933
|
+
const { scene, rootScene, set } = currentState;
|
|
934
|
+
if (scene !== oldScene) {
|
|
935
|
+
oldScene = scene;
|
|
936
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
937
|
+
set({ rootScene: scene });
|
|
938
|
+
}
|
|
926
939
|
}
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
940
|
+
});
|
|
941
|
+
let oldSize = state.size;
|
|
942
|
+
let oldDpr = state.viewport.dpr;
|
|
943
|
+
let oldCamera = state.camera;
|
|
944
|
+
rootStore.subscribe(() => {
|
|
945
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
946
|
+
const actualRenderer = internal.actualRenderer;
|
|
947
|
+
const canvasTarget = internal.canvasTarget;
|
|
948
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
949
|
+
oldSize = size;
|
|
950
|
+
oldDpr = viewport.dpr;
|
|
951
|
+
updateCamera(camera, size);
|
|
952
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
953
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
954
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
955
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
956
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
957
|
+
}
|
|
958
|
+
if (camera !== oldCamera) {
|
|
959
|
+
oldCamera = camera;
|
|
960
|
+
const { rootScene } = rootStore.getState();
|
|
961
|
+
if (camera && rootScene && !camera.parent) {
|
|
962
|
+
rootScene.add(camera);
|
|
963
|
+
}
|
|
964
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
965
|
+
const currentState = rootStore.getState();
|
|
966
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
967
|
+
updateFrustum(camera, currentState.frustum);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
});
|
|
971
|
+
rootStore.subscribe((state2) => {
|
|
972
|
+
if (state2.internal.active) invalidate(state2);
|
|
973
|
+
});
|
|
974
|
+
return rootStore;
|
|
947
975
|
};
|
|
948
976
|
|
|
949
|
-
const
|
|
950
|
-
|
|
951
|
-
const
|
|
952
|
-
const
|
|
953
|
-
const
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
977
|
+
const shallowLoose$1 = { objects: "shallow", strict: false };
|
|
978
|
+
function configureScheduler(store, canvasId, schedulerConfig, previous) {
|
|
979
|
+
const state = store.getState();
|
|
980
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
981
|
+
const rootId = state.internal.rootId;
|
|
982
|
+
const ordersItself = schedulerConfig?.before !== void 0 || schedulerConfig?.after !== void 0;
|
|
983
|
+
const rootBefore = schedulerConfig?.before;
|
|
984
|
+
const rootAfter = ordersItself ? schedulerConfig?.after : state.internal.sharedAfter;
|
|
985
|
+
if (!rootId) {
|
|
986
|
+
const newRootId = state.internal.pendingRootId ?? canvasId ?? scheduler$1.generateRootId();
|
|
987
|
+
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
988
|
+
getState: () => store.getState(),
|
|
989
|
+
onError: (err) => store.getState().setError(err),
|
|
990
|
+
frameloop: store.getState().frameloop,
|
|
991
|
+
before: rootBefore,
|
|
992
|
+
after: rootAfter,
|
|
993
|
+
order: schedulerConfig?.order
|
|
994
|
+
});
|
|
995
|
+
const unregisterCanvasTarget = scheduler$1.register(
|
|
996
|
+
() => {
|
|
997
|
+
const state2 = store.getState();
|
|
998
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
999
|
+
if (canvasTarget) {
|
|
1000
|
+
const renderer = state2.internal.actualRenderer;
|
|
1001
|
+
if (renderer.getCanvasTarget() !== canvasTarget) renderer.setCanvasTarget(canvasTarget);
|
|
1002
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
1003
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
1004
|
+
renderer.backend?.updateSize?.();
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
961
1007
|
},
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1008
|
+
{
|
|
1009
|
+
id: `${newRootId}_canvasTarget`,
|
|
1010
|
+
rootId: newRootId,
|
|
1011
|
+
phase: "start",
|
|
1012
|
+
system: true
|
|
965
1013
|
}
|
|
966
1014
|
);
|
|
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
|
-
|
|
1027
|
-
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
loadLoader(format).then((loader) => {
|
|
1048
|
-
useLoader.preload(loader, input, (loader2) => {
|
|
1049
|
-
loader2.setPath?.(path);
|
|
1050
|
-
if (extensions) extensions(loader2);
|
|
1051
|
-
});
|
|
1052
|
-
});
|
|
1053
|
-
};
|
|
1054
|
-
const clearDefaultOptins = {
|
|
1055
|
-
files: defaultFiles,
|
|
1056
|
-
preset: void 0
|
|
1057
|
-
};
|
|
1058
|
-
useEnvironment.clear = (clearOptions) => {
|
|
1059
|
-
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
1060
|
-
let { files } = options;
|
|
1061
|
-
const { preset } = options;
|
|
1062
|
-
if (preset) {
|
|
1063
|
-
validatePreset(preset);
|
|
1064
|
-
files = presetsObj[preset];
|
|
1065
|
-
}
|
|
1066
|
-
const { format } = getFormat(files);
|
|
1067
|
-
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1068
|
-
const input = isArray(files) ? [files] : files;
|
|
1069
|
-
const clear = (loader2) => useLoader.clear(loader2, input);
|
|
1070
|
-
const loader = loadedLoaders.get(format);
|
|
1071
|
-
if (loader) {
|
|
1072
|
-
clear(loader);
|
|
1015
|
+
const unregisterEventsFlush = scheduler$1.register(
|
|
1016
|
+
() => {
|
|
1017
|
+
const state2 = store.getState();
|
|
1018
|
+
state2.events.flush?.();
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
id: `${newRootId}_events`,
|
|
1022
|
+
rootId: newRootId,
|
|
1023
|
+
phase: "input",
|
|
1024
|
+
system: true
|
|
1025
|
+
}
|
|
1026
|
+
);
|
|
1027
|
+
const unregisterFrustum = scheduler$1.register(
|
|
1028
|
+
() => {
|
|
1029
|
+
const state2 = store.getState();
|
|
1030
|
+
if (state2.autoUpdateFrustum && state2.camera) {
|
|
1031
|
+
updateFrustum(state2.camera, state2.frustum);
|
|
1032
|
+
}
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
id: `${newRootId}_frustum`,
|
|
1036
|
+
rootId: newRootId,
|
|
1037
|
+
before: "render",
|
|
1038
|
+
system: true
|
|
1039
|
+
}
|
|
1040
|
+
);
|
|
1041
|
+
const unregisterVisibility = scheduler$1.register(
|
|
1042
|
+
() => {
|
|
1043
|
+
const state2 = store.getState();
|
|
1044
|
+
checkVisibility(state2);
|
|
1045
|
+
},
|
|
1046
|
+
{
|
|
1047
|
+
id: `${newRootId}_visibility`,
|
|
1048
|
+
rootId: newRootId,
|
|
1049
|
+
before: "render",
|
|
1050
|
+
system: true,
|
|
1051
|
+
after: `${newRootId}_frustum`
|
|
1052
|
+
}
|
|
1053
|
+
);
|
|
1054
|
+
const unregisterRender = scheduler$1.register(
|
|
1055
|
+
() => {
|
|
1056
|
+
const state2 = store.getState();
|
|
1057
|
+
const renderer = state2.internal.actualRenderer;
|
|
1058
|
+
const userHandlesRender = scheduler$1.hasUserJobsInPhase("render", newRootId);
|
|
1059
|
+
if (userHandlesRender || state2.internal.priority) return;
|
|
1060
|
+
try {
|
|
1061
|
+
const renderOverride = state2.internal.renderOverride;
|
|
1062
|
+
if (renderOverride) renderOverride();
|
|
1063
|
+
else if (renderer?.render) renderer.render(state2.scene, state2.camera);
|
|
1064
|
+
} catch (error) {
|
|
1065
|
+
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
1066
|
+
}
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
1070
|
+
id: canvasId || `${newRootId}_render`,
|
|
1071
|
+
rootId: newRootId,
|
|
1072
|
+
phase: "render",
|
|
1073
|
+
system: true,
|
|
1074
|
+
// Internal flag: this is a system job, not user-controlled
|
|
1075
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
1076
|
+
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
1077
|
+
}
|
|
1078
|
+
);
|
|
1079
|
+
state.set((state2) => ({
|
|
1080
|
+
internal: {
|
|
1081
|
+
...state2.internal,
|
|
1082
|
+
rootId: newRootId,
|
|
1083
|
+
pendingRootId: void 0,
|
|
1084
|
+
unregisterRoot: () => {
|
|
1085
|
+
unregisterRoot();
|
|
1086
|
+
unregisterCanvasTarget();
|
|
1087
|
+
unregisterEventsFlush();
|
|
1088
|
+
unregisterFrustum();
|
|
1089
|
+
unregisterVisibility();
|
|
1090
|
+
unregisterRender();
|
|
1091
|
+
},
|
|
1092
|
+
scheduler: scheduler$1
|
|
1093
|
+
}
|
|
1094
|
+
}));
|
|
1073
1095
|
} else {
|
|
1074
|
-
const
|
|
1075
|
-
if (
|
|
1076
|
-
|
|
1096
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, previous?.before, shallowLoose$1) || !is.equ(schedulerConfig?.after, previous?.after, shallowLoose$1);
|
|
1097
|
+
if (constraintsChanged) {
|
|
1098
|
+
scheduler$1.setRootConstraints(rootId, {
|
|
1099
|
+
before: rootBefore,
|
|
1100
|
+
after: rootAfter
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
if (schedulerConfig?.order !== previous?.order) {
|
|
1104
|
+
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
1105
|
+
}
|
|
1077
1106
|
}
|
|
1078
|
-
};
|
|
1079
|
-
function validatePreset(preset) {
|
|
1080
|
-
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
1081
|
-
}
|
|
1082
|
-
function getFormat(files) {
|
|
1083
|
-
const isCubemap = isArray(files) && files.length === 6;
|
|
1084
|
-
const firstEntry = isArray(files) ? files[0] : files;
|
|
1085
|
-
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1086
|
-
let format;
|
|
1087
|
-
if (isCubemap) format = firstExtension === "hdr" ? "hdr-cube" : "cube";
|
|
1088
|
-
else if (firstEntry.startsWith("data:application/exr")) format = "exr";
|
|
1089
|
-
else if (firstEntry.startsWith("data:application/hdr")) format = "hdr";
|
|
1090
|
-
else if (firstEntry.startsWith("data:image/jpeg")) format = "jpg";
|
|
1091
|
-
else if (firstExtension === "hdr" || firstExtension === "exr") format = firstExtension;
|
|
1092
|
-
else if (firstExtension === "jpg" || firstExtension === "jpeg") format = "jpg";
|
|
1093
|
-
return { format, isCubemap };
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
function useInstanceHandle(ref) {
|
|
1097
|
-
const instance = React.useRef(null);
|
|
1098
|
-
React.useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
1099
|
-
return instance;
|
|
1100
1107
|
}
|
|
1101
|
-
function useGraph(object) {
|
|
1102
|
-
return React.useMemo(() => buildGraph(object), [object]);
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
1108
|
let effectId = 0;
|
|
1106
1109
|
function addEffect(callback) {
|
|
1107
|
-
|
|
1110
|
+
textureStaging.notifyDepreciated({
|
|
1108
1111
|
heading: "addEffect is deprecated",
|
|
1109
1112
|
body: 'Use useFrame(callback, { phase: "start" }) instead.\naddEffect will be removed in a future version.',
|
|
1110
1113
|
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
@@ -1113,7 +1116,7 @@ function addEffect(callback) {
|
|
|
1113
1116
|
return scheduler.getScheduler().registerGlobal("before", id, callback);
|
|
1114
1117
|
}
|
|
1115
1118
|
function addAfterEffect(callback) {
|
|
1116
|
-
|
|
1119
|
+
textureStaging.notifyDepreciated({
|
|
1117
1120
|
heading: "addAfterEffect is deprecated",
|
|
1118
1121
|
body: 'Use useFrame(callback, { phase: "finish" }) instead.\naddAfterEffect will be removed in a future version.',
|
|
1119
1122
|
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
@@ -1122,7 +1125,7 @@ function addAfterEffect(callback) {
|
|
|
1122
1125
|
return scheduler.getScheduler().registerGlobal("after", id, callback);
|
|
1123
1126
|
}
|
|
1124
1127
|
function addTail(callback) {
|
|
1125
|
-
|
|
1128
|
+
textureStaging.notifyDepreciated({
|
|
1126
1129
|
heading: "addTail is deprecated",
|
|
1127
1130
|
body: "Use scheduler.onIdle(callback) instead.\naddTail will be removed in a future version.",
|
|
1128
1131
|
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
@@ -1142,107 +1145,900 @@ function advance(timestamp, runGlobalEffects, state) {
|
|
|
1142
1145
|
else scheduler$1.step(timestamp);
|
|
1143
1146
|
}
|
|
1144
1147
|
|
|
1145
|
-
const
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
+
const isPromiseLike = (value) => typeof value?.then === "function";
|
|
1149
|
+
const fulfilled = (value) => Object.assign(Promise.resolve(value), { status: "fulfilled", value });
|
|
1150
|
+
const rejected = (reason) => {
|
|
1151
|
+
const promise = Promise.reject(reason);
|
|
1152
|
+
promise.catch(() => {
|
|
1153
|
+
});
|
|
1154
|
+
return Object.assign(promise, { status: "rejected", reason });
|
|
1155
|
+
};
|
|
1156
|
+
const deferred = () => {
|
|
1157
|
+
let resolve;
|
|
1158
|
+
let reject;
|
|
1159
|
+
const promise = new Promise((yes, no) => {
|
|
1160
|
+
resolve = (value) => {
|
|
1161
|
+
Object.assign(promise, { status: "fulfilled", value });
|
|
1162
|
+
yes(value);
|
|
1163
|
+
};
|
|
1164
|
+
reject = (reason) => {
|
|
1165
|
+
Object.assign(promise, { status: "rejected", reason });
|
|
1166
|
+
no(reason);
|
|
1167
|
+
};
|
|
1168
|
+
});
|
|
1169
|
+
promise.status = "pending";
|
|
1170
|
+
promise.catch(() => {
|
|
1171
|
+
});
|
|
1172
|
+
return { promise, resolve, reject };
|
|
1173
|
+
};
|
|
1174
|
+
function resolveThen(value, apply) {
|
|
1175
|
+
return isPromiseLike(value) ? Promise.resolve(value).then(apply) : apply(value);
|
|
1176
|
+
}
|
|
1148
1177
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1178
|
+
const isRenderer = (def) => !!def?.render;
|
|
1179
|
+
function ensureStoreThreeObjects(store) {
|
|
1180
|
+
const state = store.getState();
|
|
1181
|
+
if (state.pointer) return;
|
|
1182
|
+
const { Vector2, Frustum } = getThree();
|
|
1183
|
+
const pointer = new Vector2();
|
|
1184
|
+
state.set({ pointer, mouse: pointer, frustum: new Frustum() });
|
|
1151
1185
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1186
|
+
const R3F_RENDERER_SETTINGS = ["textureColorSpace", "shadows"];
|
|
1187
|
+
const NON_APPLIED_RENDERER_PROPS = /* @__PURE__ */ new Set([
|
|
1188
|
+
...R3F_RENDERER_SETTINGS,
|
|
1189
|
+
"canvas",
|
|
1190
|
+
"antialias",
|
|
1191
|
+
"alpha",
|
|
1192
|
+
"samples",
|
|
1193
|
+
"powerPreference",
|
|
1194
|
+
"depth",
|
|
1195
|
+
"stencil",
|
|
1196
|
+
"logarithmicDepthBuffer",
|
|
1197
|
+
"reversedDepthBuffer",
|
|
1198
|
+
// WebGPURenderer only
|
|
1199
|
+
"forceWebGL",
|
|
1200
|
+
"outputBufferType",
|
|
1201
|
+
"multiview",
|
|
1202
|
+
"getFallback",
|
|
1203
|
+
"trackTimestamp"
|
|
1204
|
+
]);
|
|
1205
|
+
function settingsBag(config) {
|
|
1206
|
+
return is.obj(config) && !isRenderer(config) ? config : void 0;
|
|
1207
|
+
}
|
|
1208
|
+
function isInstanceOrFactory(config) {
|
|
1209
|
+
return is.fun(config) || isRenderer(config);
|
|
1210
|
+
}
|
|
1211
|
+
function assertNoRemovedConfig(props) {
|
|
1212
|
+
if (props.primaryCanvas !== void 0) {
|
|
1213
|
+
throw new Error(
|
|
1214
|
+
'R3F: `primaryCanvas` was removed: mark the owner <Canvas primary> and other canvases share it automatically (or use share="id")'
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
if (props.shadows !== void 0) {
|
|
1218
|
+
throw new Error(
|
|
1219
|
+
"R3F: the `shadows` Canvas prop moved into the renderer settings: use `renderer={{ shadows }}` (or `gl={{ shadows }}` for WebGL and @react-three/fiber/legacy)"
|
|
1220
|
+
);
|
|
1221
|
+
}
|
|
1222
|
+
for (const name of ["renderer", "gl"]) {
|
|
1223
|
+
const bag = settingsBag(props[name]);
|
|
1224
|
+
if (!bag) continue;
|
|
1225
|
+
if ("primaryCanvas" in bag) {
|
|
1226
|
+
throw new Error(
|
|
1227
|
+
`R3F: \`${name}={{ primaryCanvas }}\` was removed: mark the owner <Canvas primary> and other canvases share it automatically (or use share="id")`
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
if ("scheduler" in bag) {
|
|
1231
|
+
throw new Error(`R3F: \`${name}={{ scheduler }}\` moved to <Canvas scheduler>`);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
function resolveRenderer(config, defaultProps, RendererClass) {
|
|
1236
|
+
if (typeof config === "function") {
|
|
1237
|
+
return resolveThen(config(defaultProps), (renderer) => ({
|
|
1238
|
+
renderer,
|
|
1239
|
+
owned: true
|
|
1240
|
+
}));
|
|
1241
|
+
}
|
|
1242
|
+
if (isRenderer(config)) return { renderer: config, owned: false };
|
|
1243
|
+
const params = { ...defaultProps };
|
|
1244
|
+
for (const key in settingsBag(config)) if (!R3F_RENDERER_SETTINGS.includes(key)) params[key] = config[key];
|
|
1245
|
+
return { renderer: new RendererClass(params), owned: true };
|
|
1246
|
+
}
|
|
1247
|
+
function createOwnedWebGPURenderer(rendererConfig, defaultGPUProps, canvas, propsSize, dpr, support) {
|
|
1248
|
+
return resolveThen(resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer), (resolved) => {
|
|
1249
|
+
const renderer = resolved.renderer;
|
|
1250
|
+
if (!renderer.hasInitialized?.()) {
|
|
1251
|
+
const size = computeInitialSize(canvas, propsSize);
|
|
1252
|
+
if (size.width > 0 && size.height > 0) {
|
|
1253
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
1254
|
+
renderer.setSize(size.width, size.height, false);
|
|
1168
1255
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1256
|
+
return resolveThen(renderer.init(), () => ({ renderer, owned: resolved.owned }));
|
|
1257
|
+
}
|
|
1258
|
+
return { renderer, owned: resolved.owned };
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
function initializeRenderer(canvas, provider, store, props) {
|
|
1262
|
+
const {
|
|
1263
|
+
id: canvasId,
|
|
1264
|
+
primary = false,
|
|
1265
|
+
share,
|
|
1266
|
+
gl: glConfig,
|
|
1267
|
+
renderer: rendererConfig,
|
|
1268
|
+
size: propsSize,
|
|
1269
|
+
dpr = [1, 2],
|
|
1270
|
+
_primaryToken
|
|
1271
|
+
} = props;
|
|
1272
|
+
assertNoRemovedConfig(props);
|
|
1273
|
+
const rendererBag = settingsBag(rendererConfig);
|
|
1274
|
+
const state = store.getState();
|
|
1275
|
+
const { webgl, webgpu } = provider;
|
|
1276
|
+
const defaultGLProps = {
|
|
1277
|
+
canvas,
|
|
1278
|
+
powerPreference: "high-performance",
|
|
1279
|
+
antialias: true,
|
|
1280
|
+
alpha: true
|
|
1281
|
+
};
|
|
1282
|
+
const defaultGPUProps = {
|
|
1283
|
+
canvas,
|
|
1284
|
+
antialias: true
|
|
1285
|
+
};
|
|
1286
|
+
if (glConfig && !webgl) {
|
|
1287
|
+
throw new Error(
|
|
1288
|
+
"WebGLRenderer (gl prop) is not available on this entry. Use @react-three/fiber or @react-three/fiber/legacy instead."
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
if (rendererConfig && !webgpu) {
|
|
1292
|
+
throw new Error(
|
|
1293
|
+
"WebGPURenderer (renderer prop) is not available on this entry. Use @react-three/fiber or @react-three/fiber/webgpu instead."
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
if (glConfig && rendererConfig) {
|
|
1297
|
+
throw new Error("Cannot use both gl and renderer props at the same time");
|
|
1298
|
+
}
|
|
1299
|
+
if (primary && !webgpu) {
|
|
1300
|
+
throw new Error(
|
|
1301
|
+
"R3F: <Canvas primary> shares a WebGPU renderer and is not available on this entry. Use @react-three/fiber or @react-three/fiber/webgpu instead."
|
|
1302
|
+
);
|
|
1303
|
+
}
|
|
1304
|
+
if (primary && glConfig) {
|
|
1305
|
+
throw new Error(
|
|
1306
|
+
"R3F: <Canvas primary> shares a WebGPU renderer and cannot be used with WebGL. Remove the `gl` prop or use the `renderer` prop."
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
if (primary && is.str(share)) {
|
|
1310
|
+
throw new Error(`R3F: a <Canvas primary> owns its renderer; remove share="${share}" from it.`);
|
|
1311
|
+
}
|
|
1312
|
+
if (is.str(share)) {
|
|
1313
|
+
if (!webgpu || glConfig) {
|
|
1314
|
+
throw new Error(
|
|
1315
|
+
`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.`
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
if (isInstanceOrFactory(rendererConfig)) {
|
|
1319
|
+
throw new Error(
|
|
1320
|
+
`R3F: share="${share}" borrows the primary's renderer, so it cannot be combined with a renderer instance or factory. Remove one of the two.`
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
const primaryKey = canvasId || DEFAULT_PRIMARY;
|
|
1325
|
+
const primaryToken = _primaryToken ?? store;
|
|
1326
|
+
if (primary && !state.internal.actualRenderer) {
|
|
1327
|
+
announcePrimary(primaryKey, primaryToken);
|
|
1328
|
+
state.internal.unregisterPrimary = () => withdrawPrimary(primaryKey, primaryToken);
|
|
1329
|
+
if (primaryConflict(primaryKey, primaryToken)) {
|
|
1330
|
+
throw new Error(
|
|
1331
|
+
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\`.`
|
|
1332
|
+
);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
let shareKey;
|
|
1336
|
+
if (!state.internal.actualRenderer && webgpu && !primary && !glConfig && !state.isLegacy) {
|
|
1337
|
+
if (is.str(share)) {
|
|
1338
|
+
shareKey = share;
|
|
1339
|
+
} else if (share !== false && !isInstanceOrFactory(rendererConfig)) {
|
|
1340
|
+
const live = livePrimaryKeys();
|
|
1341
|
+
if (live.length > 1) {
|
|
1342
|
+
throw new Error(
|
|
1343
|
+
`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.`
|
|
1344
|
+
);
|
|
1173
1345
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1346
|
+
shareKey = live[0];
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
const explicitShare = is.str(share);
|
|
1350
|
+
const wantsGL = !!webgl && (state.isLegacy || !!glConfig || !webgpu || !rendererConfig && !primary && shareKey === void 0);
|
|
1351
|
+
if (webgl && webgpu && !state.isLegacy && wantsGL) {
|
|
1352
|
+
textureStaging.notifyDepreciated({
|
|
1353
|
+
heading: "WebGlRenderer Usage",
|
|
1354
|
+
body: "WebGlRenderer usage is deprecated in favor of WebGPU. Import from /legacy directly or upgrade to WebGPU.",
|
|
1355
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/renderer"
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
let renderer = state.internal.actualRenderer;
|
|
1359
|
+
if (!state.internal.actualRenderer) {
|
|
1360
|
+
return resolveThen(wantsGL ? webgl() : webgpu(), (support) => {
|
|
1361
|
+
registerThree(support.three);
|
|
1362
|
+
state.internal.support = support;
|
|
1363
|
+
ensureStoreThreeObjects(store);
|
|
1364
|
+
if (support.kind === "webgl") {
|
|
1365
|
+
return resolveThen(resolveRenderer(glConfig, defaultGLProps, support.Renderer), (resolved) => {
|
|
1366
|
+
renderer = resolved.renderer;
|
|
1367
|
+
state.internal.actualRenderer = renderer;
|
|
1368
|
+
state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
|
|
1369
|
+
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
1370
|
+
});
|
|
1176
1371
|
}
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
if (
|
|
1180
|
-
|
|
1181
|
-
|
|
1372
|
+
const primaryReady = shareKey === void 0 ? null : explicitShare ? waitForPrimary(shareKey) : waitForAnnouncedPrimary(shareKey);
|
|
1373
|
+
return resolveThen(primaryReady, (primaryEntry) => {
|
|
1374
|
+
if (primaryEntry && primaryEntry.store.getState().webGPUSupported) {
|
|
1375
|
+
renderer = primaryEntry.renderer;
|
|
1376
|
+
state.internal.actualRenderer = renderer;
|
|
1377
|
+
state.internal.releaseRenderer = borrowRenderer(renderer);
|
|
1378
|
+
state.internal.sharedAfter = primaryEntry.rootId;
|
|
1379
|
+
const canvasTarget = new support.CanvasTarget(canvas);
|
|
1380
|
+
primaryEntry.store.setState((prev) => ({
|
|
1381
|
+
internal: { ...prev.internal, isMultiCanvas: true }
|
|
1382
|
+
}));
|
|
1383
|
+
state.set((prev) => ({
|
|
1384
|
+
webGPUSupported: primaryEntry.store.getState().webGPUSupported,
|
|
1385
|
+
renderer,
|
|
1386
|
+
primaryStore: primaryEntry.store,
|
|
1387
|
+
internal: {
|
|
1388
|
+
...prev.internal,
|
|
1389
|
+
canvasTarget,
|
|
1390
|
+
isMultiCanvas: true,
|
|
1391
|
+
isSecondary: true,
|
|
1392
|
+
targetId: shareKey === DEFAULT_PRIMARY ? void 0 : shareKey
|
|
1393
|
+
}
|
|
1394
|
+
}));
|
|
1395
|
+
return;
|
|
1182
1396
|
}
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1397
|
+
if (primaryEntry) {
|
|
1398
|
+
return resolveThen(
|
|
1399
|
+
createOwnedWebGPURenderer(
|
|
1400
|
+
{ ...rendererBag, forceWebGL: true },
|
|
1401
|
+
defaultGPUProps,
|
|
1402
|
+
canvas,
|
|
1403
|
+
propsSize,
|
|
1404
|
+
dpr,
|
|
1405
|
+
support
|
|
1406
|
+
),
|
|
1407
|
+
(resolved) => {
|
|
1408
|
+
renderer = resolved.renderer;
|
|
1409
|
+
const backend = renderer.backend;
|
|
1410
|
+
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
1411
|
+
state.internal.actualRenderer = renderer;
|
|
1412
|
+
state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
|
|
1413
|
+
state.set((prev) => ({
|
|
1414
|
+
webGPUSupported: isWebGPUBackend,
|
|
1415
|
+
renderer,
|
|
1416
|
+
primaryStore: store,
|
|
1417
|
+
internal: {
|
|
1418
|
+
...prev.internal,
|
|
1419
|
+
canvasTarget: renderer.getCanvasTarget?.(),
|
|
1420
|
+
sharedRendererFallback: true
|
|
1421
|
+
}
|
|
1422
|
+
}));
|
|
1191
1423
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
return resolveThen(
|
|
1427
|
+
createOwnedWebGPURenderer(rendererConfig, defaultGPUProps, canvas, propsSize, dpr, support),
|
|
1428
|
+
(resolved) => {
|
|
1429
|
+
var _a;
|
|
1430
|
+
renderer = resolved.renderer;
|
|
1431
|
+
const backend = renderer.backend;
|
|
1432
|
+
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
1433
|
+
state.internal.actualRenderer = renderer;
|
|
1434
|
+
state.internal.releaseRenderer = leaseRenderer(renderer, resolved.owned);
|
|
1435
|
+
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
1436
|
+
if (primary) {
|
|
1437
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
1438
|
+
(_a = state.internal).pendingRootId ?? (_a.pendingRootId = canvasId || scheduler.getScheduler().generateRootId());
|
|
1439
|
+
registerPrimary(primaryKey, renderer, store, {
|
|
1440
|
+
token: primaryToken,
|
|
1441
|
+
rootId: state.internal.pendingRootId
|
|
1442
|
+
});
|
|
1443
|
+
state.set((prev) => ({ internal: { ...prev.internal, canvasTarget } }));
|
|
1444
|
+
} else if (share !== false && !isInstanceOrFactory(rendererConfig)) {
|
|
1445
|
+
state.internal.untrackStandalone = trackStandalone(store);
|
|
1199
1446
|
}
|
|
1200
|
-
throw Error(F(188));
|
|
1201
1447
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1448
|
+
);
|
|
1449
|
+
});
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
const records = /* @__PURE__ */ new WeakMap();
|
|
1454
|
+
function take(renderer, record) {
|
|
1455
|
+
record.leases++;
|
|
1456
|
+
let released = false;
|
|
1457
|
+
return () => {
|
|
1458
|
+
if (released) return;
|
|
1459
|
+
released = true;
|
|
1460
|
+
if (--record.leases > 0) return;
|
|
1461
|
+
records.delete(renderer);
|
|
1462
|
+
if (record.owned) return disposeRenderer(renderer);
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
function leaseRenderer(renderer, owned) {
|
|
1466
|
+
let record = records.get(renderer);
|
|
1467
|
+
if (!record) records.set(renderer, record = { owned, leases: 0 });
|
|
1468
|
+
return take(renderer, record);
|
|
1469
|
+
}
|
|
1470
|
+
function borrowRenderer(renderer) {
|
|
1471
|
+
const record = records.get(renderer);
|
|
1472
|
+
if (!record) throw new Error("R3F: cannot share a renderer whose canvas has already unmounted");
|
|
1473
|
+
return take(renderer, record);
|
|
1474
|
+
}
|
|
1475
|
+
function disposeRenderer(renderer) {
|
|
1476
|
+
if (renderer.hasInitialized?.() === false) return;
|
|
1477
|
+
const warn = (error) => console.warn("[R3F] Error disposing renderer", error);
|
|
1478
|
+
const loseContext = () => {
|
|
1479
|
+
try {
|
|
1480
|
+
;
|
|
1481
|
+
renderer.forceContextLoss?.();
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
warn(error);
|
|
1484
|
+
}
|
|
1485
|
+
};
|
|
1486
|
+
let disposed;
|
|
1487
|
+
try {
|
|
1488
|
+
disposed = renderer.dispose ? renderer.dispose() : renderer.renderLists?.dispose?.();
|
|
1489
|
+
} catch (error) {
|
|
1490
|
+
warn(error);
|
|
1491
|
+
}
|
|
1492
|
+
if (typeof disposed?.then === "function") {
|
|
1493
|
+
return Promise.resolve(disposed).then(loseContext, (error) => {
|
|
1494
|
+
warn(error);
|
|
1495
|
+
loseContext();
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
loseContext();
|
|
1499
|
+
}
|
|
1500
|
+
const DEFAULT_PRIMARY = "\0r3f:primary";
|
|
1501
|
+
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
1502
|
+
const announcements = /* @__PURE__ */ new Map();
|
|
1503
|
+
const withdrawing = /* @__PURE__ */ new Set();
|
|
1504
|
+
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
1505
|
+
const standaloneRoots = /* @__PURE__ */ new Set();
|
|
1506
|
+
const warnedLatePrimary = /* @__PURE__ */ new WeakSet();
|
|
1507
|
+
function describePrimary(key) {
|
|
1508
|
+
return key === DEFAULT_PRIMARY ? "<Canvas primary>" : `<Canvas id="${key}" primary>`;
|
|
1509
|
+
}
|
|
1510
|
+
function notify(key, entry) {
|
|
1511
|
+
const subscribers = pendingSubscribers.get(key);
|
|
1512
|
+
if (!subscribers) return;
|
|
1513
|
+
pendingSubscribers.delete(key);
|
|
1514
|
+
subscribers.forEach((callback) => callback(entry));
|
|
1515
|
+
}
|
|
1516
|
+
function isLive(key) {
|
|
1517
|
+
const owners = announcements.get(key);
|
|
1518
|
+
if (owners) {
|
|
1519
|
+
for (const owner of owners) if (!withdrawing.has(owner)) return true;
|
|
1520
|
+
}
|
|
1521
|
+
const entry = primaryRegistry.get(key);
|
|
1522
|
+
return !!entry && !(entry.token && withdrawing.has(entry.token));
|
|
1523
|
+
}
|
|
1524
|
+
function announcePrimary(key, owner) {
|
|
1525
|
+
withdrawing.delete(owner);
|
|
1526
|
+
let owners = announcements.get(key);
|
|
1527
|
+
if (!owners) announcements.set(key, owners = /* @__PURE__ */ new Set());
|
|
1528
|
+
if (owners.has(owner)) return;
|
|
1529
|
+
owners.add(owner);
|
|
1530
|
+
if (standaloneRoots.size > 0 && !warnedLatePrimary.has(owner) && textureStaging.isDevelopment()) {
|
|
1531
|
+
warnedLatePrimary.add(owner);
|
|
1532
|
+
console.warn(
|
|
1533
|
+
`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.`
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
function markWithdrawing(owner) {
|
|
1538
|
+
withdrawing.add(owner);
|
|
1539
|
+
}
|
|
1540
|
+
function withdrawPrimary(key, owner) {
|
|
1541
|
+
withdrawing.delete(owner);
|
|
1542
|
+
const owners = announcements.get(key);
|
|
1543
|
+
if (owners) {
|
|
1544
|
+
owners.delete(owner);
|
|
1545
|
+
if (owners.size === 0) announcements.delete(key);
|
|
1546
|
+
}
|
|
1547
|
+
const entry = primaryRegistry.get(key);
|
|
1548
|
+
if (entry?.token === owner) primaryRegistry.delete(key);
|
|
1549
|
+
if (!isLive(key)) notify(key, null);
|
|
1550
|
+
}
|
|
1551
|
+
function primaryConflict(key, owner) {
|
|
1552
|
+
const owners = announcements.get(key);
|
|
1553
|
+
if (owners) {
|
|
1554
|
+
for (const other of owners) {
|
|
1555
|
+
if (other === owner) break;
|
|
1556
|
+
if (!withdrawing.has(other)) return true;
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
const entry = primaryRegistry.get(key);
|
|
1560
|
+
return !!entry && entry.token !== owner && !(entry.token && withdrawing.has(entry.token));
|
|
1561
|
+
}
|
|
1562
|
+
function livePrimaryKeys() {
|
|
1563
|
+
const keys = /* @__PURE__ */ new Set([...announcements.keys(), ...primaryRegistry.keys()]);
|
|
1564
|
+
return [...keys].filter(isLive);
|
|
1565
|
+
}
|
|
1566
|
+
function trackStandalone(owner) {
|
|
1567
|
+
standaloneRoots.add(owner);
|
|
1568
|
+
return () => {
|
|
1569
|
+
standaloneRoots.delete(owner);
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
function registerPrimary(id, renderer, store, options = {}) {
|
|
1573
|
+
if (options.token && !announcements.get(id)?.has(options.token)) return () => {
|
|
1574
|
+
};
|
|
1575
|
+
if (primaryRegistry.has(id)) {
|
|
1576
|
+
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
1577
|
+
}
|
|
1578
|
+
const entry = { renderer, store, rootId: options.rootId, token: options.token };
|
|
1579
|
+
primaryRegistry.set(id, entry);
|
|
1580
|
+
notify(id, entry);
|
|
1581
|
+
return () => {
|
|
1582
|
+
const currentEntry = primaryRegistry.get(id);
|
|
1583
|
+
if (currentEntry?.renderer === renderer) {
|
|
1584
|
+
primaryRegistry.delete(id);
|
|
1585
|
+
}
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
function getPrimary(id) {
|
|
1589
|
+
return primaryRegistry.get(id);
|
|
1590
|
+
}
|
|
1591
|
+
function subscribe(id, callback) {
|
|
1592
|
+
if (!pendingSubscribers.has(id)) pendingSubscribers.set(id, []);
|
|
1593
|
+
pendingSubscribers.get(id).push(callback);
|
|
1594
|
+
return () => {
|
|
1595
|
+
const subscribers = pendingSubscribers.get(id);
|
|
1596
|
+
if (!subscribers) return;
|
|
1597
|
+
const index = subscribers.indexOf(callback);
|
|
1598
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
1599
|
+
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
function waitForPrimary(id, timeout = 5e3) {
|
|
1603
|
+
const existing = primaryRegistry.get(id);
|
|
1604
|
+
if (existing) {
|
|
1605
|
+
return Promise.resolve(existing);
|
|
1606
|
+
}
|
|
1607
|
+
return new Promise((resolve, reject) => {
|
|
1608
|
+
let unsubscribe = () => {
|
|
1609
|
+
};
|
|
1610
|
+
const timeoutId = setTimeout(() => {
|
|
1611
|
+
unsubscribe();
|
|
1612
|
+
reject(
|
|
1613
|
+
new Error(
|
|
1614
|
+
`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}" primary> is mounted for share="${id}".`
|
|
1615
|
+
)
|
|
1616
|
+
);
|
|
1617
|
+
}, timeout);
|
|
1618
|
+
const callback = (entry) => {
|
|
1619
|
+
if (!entry) {
|
|
1620
|
+
unsubscribe = subscribe(id, callback);
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
clearTimeout(timeoutId);
|
|
1624
|
+
resolve(entry);
|
|
1625
|
+
};
|
|
1626
|
+
unsubscribe = subscribe(id, callback);
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
function waitForAnnouncedPrimary(key, timeout = 5e3) {
|
|
1630
|
+
const existing = primaryRegistry.get(key);
|
|
1631
|
+
if (existing && isLive(key)) return Promise.resolve(existing);
|
|
1632
|
+
if (!isLive(key)) return Promise.resolve(null);
|
|
1633
|
+
return new Promise((resolve, reject) => {
|
|
1634
|
+
const timeoutId = setTimeout(() => {
|
|
1635
|
+
unsubscribe();
|
|
1636
|
+
reject(
|
|
1637
|
+
new Error(
|
|
1638
|
+
`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.`
|
|
1639
|
+
)
|
|
1640
|
+
);
|
|
1641
|
+
}, timeout);
|
|
1642
|
+
const unsubscribe = subscribe(key, (entry) => {
|
|
1643
|
+
clearTimeout(timeoutId);
|
|
1644
|
+
resolve(entry);
|
|
1645
|
+
});
|
|
1646
|
+
});
|
|
1647
|
+
}
|
|
1648
|
+
function hasPrimary(id) {
|
|
1649
|
+
return primaryRegistry.has(id);
|
|
1650
|
+
}
|
|
1651
|
+
function unregisterPrimary(id) {
|
|
1652
|
+
primaryRegistry.delete(id);
|
|
1653
|
+
}
|
|
1654
|
+
function getPrimaryIds() {
|
|
1655
|
+
return Array.from(primaryRegistry.keys());
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
const shallowLoose = { objects: "shallow", strict: false };
|
|
1659
|
+
function watchDpr(onChange) {
|
|
1660
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function" || !window.devicePixelRatio) {
|
|
1661
|
+
return () => {
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
let watching = true;
|
|
1665
|
+
let query;
|
|
1666
|
+
const listen = () => {
|
|
1667
|
+
try {
|
|
1668
|
+
query = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
1669
|
+
if (typeof query?.addEventListener === "function") query.addEventListener("change", handleChange);
|
|
1670
|
+
else query?.addListener?.(handleChange);
|
|
1671
|
+
} catch {
|
|
1672
|
+
query = void 0;
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
const unlisten = () => {
|
|
1676
|
+
if (typeof query?.removeEventListener === "function") query.removeEventListener("change", handleChange);
|
|
1677
|
+
else query?.removeListener?.(handleChange);
|
|
1678
|
+
query = void 0;
|
|
1679
|
+
};
|
|
1680
|
+
const handleChange = () => {
|
|
1681
|
+
if (!watching) return;
|
|
1682
|
+
unlisten();
|
|
1683
|
+
listen();
|
|
1684
|
+
onChange();
|
|
1685
|
+
};
|
|
1686
|
+
listen();
|
|
1687
|
+
return () => {
|
|
1688
|
+
watching = false;
|
|
1689
|
+
unlisten();
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
function createRootConfiguration(store, canvas) {
|
|
1693
|
+
let previous;
|
|
1694
|
+
let lastCamera;
|
|
1695
|
+
const lastConfiguredProps = {};
|
|
1696
|
+
let resolvedDpr = 0;
|
|
1697
|
+
let dprChangedInXR = false;
|
|
1698
|
+
let unwatchDpr;
|
|
1699
|
+
const resolveDpr = () => {
|
|
1700
|
+
const state = store.getState();
|
|
1701
|
+
const xr = state.internal.actualRenderer?.xr;
|
|
1702
|
+
if (xr?.isPresenting || xr?.getSession?.()) {
|
|
1703
|
+
dprChangedInXR = true;
|
|
1704
|
+
return;
|
|
1705
|
+
}
|
|
1706
|
+
dprChangedInXR = false;
|
|
1707
|
+
const dpr = lastConfiguredProps.dpr;
|
|
1708
|
+
if (dpr === void 0 || state.viewport.dpr !== resolvedDpr || calculateDpr(dpr) === resolvedDpr) return;
|
|
1709
|
+
state.setDpr(dpr);
|
|
1710
|
+
resolvedDpr = store.getState().viewport.dpr;
|
|
1711
|
+
};
|
|
1712
|
+
let warnedSharedSettings = false;
|
|
1713
|
+
let configured = false;
|
|
1714
|
+
return (props) => {
|
|
1715
|
+
const {
|
|
1716
|
+
gl: glConfig,
|
|
1717
|
+
renderer: rendererConfig,
|
|
1718
|
+
size: propsSize,
|
|
1719
|
+
scene: sceneOptions,
|
|
1720
|
+
events,
|
|
1721
|
+
orthographic = false,
|
|
1722
|
+
frameloop = "always",
|
|
1723
|
+
dpr = [1, 2],
|
|
1724
|
+
performance,
|
|
1725
|
+
raycaster: raycastOptions,
|
|
1726
|
+
camera: cameraOptions,
|
|
1727
|
+
onPointerMissed,
|
|
1728
|
+
onDragOverMissed,
|
|
1729
|
+
onDropMissed,
|
|
1730
|
+
autoUpdateFrustum = true,
|
|
1731
|
+
occlusion = false,
|
|
1732
|
+
_sizeProps,
|
|
1733
|
+
forceEven
|
|
1734
|
+
} = props;
|
|
1735
|
+
assertNoRemovedConfig(props);
|
|
1736
|
+
const rendererBag = settingsBag(rendererConfig);
|
|
1737
|
+
const settings = settingsBag(glConfig) ?? rendererBag;
|
|
1738
|
+
const requestedTextureColorSpace = settings?.textureColorSpace || void 0;
|
|
1739
|
+
const shadows = isInstanceOrFactory(glConfig ?? rendererConfig) ? void 0 : settings?.shadows ?? false;
|
|
1740
|
+
const next = { ...props, shadows, frameloop, autoUpdateFrustum, occlusion };
|
|
1741
|
+
const last = previous;
|
|
1742
|
+
const changed = (key) => !last || !is.equ(next[key], last[key], { objects: "shallow" });
|
|
1743
|
+
previous = void 0;
|
|
1744
|
+
const state = store.getState();
|
|
1745
|
+
const renderer = state.internal.actualRenderer;
|
|
1746
|
+
const three = getThree();
|
|
1747
|
+
const borrowsRenderer = state.internal.isSecondary === true;
|
|
1748
|
+
if (borrowsRenderer && !warnedSharedSettings && rendererBag && Object.keys(rendererBag).some((key) => key !== "textureColorSpace") && textureStaging.isDevelopment()) {
|
|
1749
|
+
warnedSharedSettings = true;
|
|
1750
|
+
console.warn(
|
|
1751
|
+
"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."
|
|
1752
|
+
);
|
|
1753
|
+
}
|
|
1754
|
+
let raycaster = state.raycaster;
|
|
1755
|
+
if (!raycaster) state.set({ raycaster: raycaster = new three.Raycaster() });
|
|
1756
|
+
if (changed("raycaster")) {
|
|
1757
|
+
const { params, ...options } = raycastOptions || {};
|
|
1758
|
+
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options });
|
|
1759
|
+
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
1760
|
+
applyProps(raycaster, { params: { ...raycaster.params, ...params } });
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
let tempCamera = state.camera;
|
|
1764
|
+
if (!state.camera || state.camera === lastCamera && changed("camera")) {
|
|
1765
|
+
lastCamera = cameraOptions;
|
|
1766
|
+
const isCamera = cameraOptions?.isCamera;
|
|
1767
|
+
const camera = isCamera ? cameraOptions : orthographic ? new three.OrthographicCamera(0, 0, 0, 0, 0.1, 1e3) : new three.PerspectiveCamera(50, 0, 0.1, 1e3);
|
|
1768
|
+
if (!isCamera) {
|
|
1769
|
+
camera.position.z = 5;
|
|
1770
|
+
if (cameraOptions) {
|
|
1771
|
+
applyProps(camera, cameraOptions);
|
|
1772
|
+
if (!camera.manual) {
|
|
1773
|
+
const projectionProps = ["aspect", "left", "right", "bottom", "top"];
|
|
1774
|
+
if (projectionProps.some((prop) => prop in cameraOptions)) {
|
|
1775
|
+
camera.manual = true;
|
|
1776
|
+
camera.updateProjectionMatrix();
|
|
1228
1777
|
}
|
|
1229
1778
|
}
|
|
1230
|
-
if (a.alternate !== l) throw Error(F(190));
|
|
1231
|
-
}
|
|
1232
|
-
if (a.tag !== 3) throw Error(F(188));
|
|
1233
|
-
return a.stateNode.current === a ? t : r;
|
|
1234
|
-
}
|
|
1235
|
-
function mc(t) {
|
|
1236
|
-
var r = t.tag;
|
|
1237
|
-
if (r === 5 || r === 26 || r === 27 || r === 6) return t;
|
|
1238
|
-
for (t = t.child; t !== null; ) {
|
|
1239
|
-
if (r = mc(t), r !== null) return r;
|
|
1240
|
-
t = t.sibling;
|
|
1241
1779
|
}
|
|
1242
|
-
|
|
1780
|
+
if (!state.camera && !cameraOptions?.rotation) camera.lookAt(0, 0, 0);
|
|
1243
1781
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1782
|
+
state.set({ camera });
|
|
1783
|
+
tempCamera = camera;
|
|
1784
|
+
raycaster.camera = camera;
|
|
1785
|
+
}
|
|
1786
|
+
if (!state.scene) {
|
|
1787
|
+
let scene;
|
|
1788
|
+
if (sceneOptions?.isScene) {
|
|
1789
|
+
scene = sceneOptions;
|
|
1790
|
+
prepare(scene, store, "", {});
|
|
1791
|
+
} else {
|
|
1792
|
+
scene = new three.Scene();
|
|
1793
|
+
prepare(scene, store, "", {});
|
|
1794
|
+
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
1795
|
+
}
|
|
1796
|
+
state.set((prev) => ({
|
|
1797
|
+
scene,
|
|
1798
|
+
rootScene: scene,
|
|
1799
|
+
internal: { ...prev.internal, container: scene }
|
|
1800
|
+
}));
|
|
1801
|
+
const camera = tempCamera;
|
|
1802
|
+
if (camera && !camera.parent) scene.add(camera);
|
|
1803
|
+
}
|
|
1804
|
+
if (events && !state.events.handlers) {
|
|
1805
|
+
state.set({ events: events(store) });
|
|
1806
|
+
let wasEnabled = true;
|
|
1807
|
+
store.subscribe((state2) => {
|
|
1808
|
+
const { enabled } = state2.events;
|
|
1809
|
+
if (enabled && !wasEnabled) {
|
|
1810
|
+
state2.events.update?.();
|
|
1811
|
+
}
|
|
1812
|
+
wasEnabled = enabled;
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
if (_sizeProps !== void 0 && changed("_sizeProps")) {
|
|
1816
|
+
state.set({ _sizeProps });
|
|
1817
|
+
}
|
|
1818
|
+
if (forceEven !== void 0 && state.internal.forceEven !== forceEven) {
|
|
1819
|
+
state.set((prev) => ({ internal: { ...prev.internal, forceEven } }));
|
|
1820
|
+
}
|
|
1821
|
+
configureSize(store, computeInitialSize(canvas, propsSize));
|
|
1822
|
+
if (dpr !== void 0 && (!last || !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose))) {
|
|
1823
|
+
state.setDpr(dpr);
|
|
1824
|
+
lastConfiguredProps.dpr = dpr;
|
|
1825
|
+
resolvedDpr = store.getState().viewport.dpr;
|
|
1826
|
+
}
|
|
1827
|
+
const internal = store.getState().internal;
|
|
1828
|
+
if (Array.isArray(dpr) && (!unwatchDpr || internal.unwatchDpr !== unwatchDpr)) {
|
|
1829
|
+
internal.unwatchDpr?.();
|
|
1830
|
+
internal.unwatchDpr = unwatchDpr = watchDpr(resolveDpr);
|
|
1831
|
+
}
|
|
1832
|
+
resolveDpr();
|
|
1833
|
+
if (frameloop !== void 0 && changed("frameloop")) {
|
|
1834
|
+
state.setFrameloop(frameloop);
|
|
1835
|
+
}
|
|
1836
|
+
if (changed("onPointerMissed")) state.set({ onPointerMissed });
|
|
1837
|
+
if (changed("onDragOverMissed")) state.set({ onDragOverMissed });
|
|
1838
|
+
if (changed("onDropMissed")) state.set({ onDropMissed });
|
|
1839
|
+
if (changed("autoUpdateFrustum") && state.autoUpdateFrustum !== autoUpdateFrustum) {
|
|
1840
|
+
state.set({ autoUpdateFrustum });
|
|
1841
|
+
}
|
|
1842
|
+
if (occlusion && !state.internal.occlusionEnabled) {
|
|
1843
|
+
enableOcclusion(store);
|
|
1844
|
+
}
|
|
1845
|
+
if (performance && changed("performance")) {
|
|
1846
|
+
state.set((state2) => ({ performance: { ...state2.performance, ...performance } }));
|
|
1847
|
+
}
|
|
1848
|
+
if (!state.xr) {
|
|
1849
|
+
const handleXRFrame = (timestamp, _frame) => {
|
|
1850
|
+
const state2 = store.getState();
|
|
1851
|
+
if (state2.frameloop === "never") return;
|
|
1852
|
+
advance(timestamp, true, state2);
|
|
1853
|
+
};
|
|
1854
|
+
const actualRenderer = state.internal.actualRenderer;
|
|
1855
|
+
const handleSessionChange = () => {
|
|
1856
|
+
const state2 = store.getState();
|
|
1857
|
+
const renderer2 = state2.internal.actualRenderer;
|
|
1858
|
+
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
1859
|
+
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
1860
|
+
if (!renderer2.xr.isPresenting) {
|
|
1861
|
+
if (dprChangedInXR) resolveDpr();
|
|
1862
|
+
invalidate(state2);
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
const xr = {
|
|
1866
|
+
connect() {
|
|
1867
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
1868
|
+
const xrManager = (renderer2 || gl).xr;
|
|
1869
|
+
xrManager.addEventListener("sessionstart", handleSessionChange);
|
|
1870
|
+
xrManager.addEventListener("sessionend", handleSessionChange);
|
|
1871
|
+
},
|
|
1872
|
+
disconnect() {
|
|
1873
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
1874
|
+
const xrManager = (renderer2 || gl).xr;
|
|
1875
|
+
xrManager.removeEventListener("sessionstart", handleSessionChange);
|
|
1876
|
+
xrManager.removeEventListener("sessionend", handleSessionChange);
|
|
1877
|
+
}
|
|
1878
|
+
};
|
|
1879
|
+
if (!borrowsRenderer && typeof renderer.xr?.addEventListener === "function") xr.connect();
|
|
1880
|
+
state.set({ xr });
|
|
1881
|
+
}
|
|
1882
|
+
if (!borrowsRenderer && shadows !== void 0 && renderer.shadowMap && changed("shadows")) {
|
|
1883
|
+
const oldEnabled = renderer.shadowMap.enabled;
|
|
1884
|
+
const oldType = renderer.shadowMap.type;
|
|
1885
|
+
renderer.shadowMap.enabled = !!shadows;
|
|
1886
|
+
if (is.boo(shadows)) {
|
|
1887
|
+
renderer.shadowMap.type = three.PCFShadowMap;
|
|
1888
|
+
} else if (is.str(shadows)) {
|
|
1889
|
+
if (shadows === "soft") {
|
|
1890
|
+
textureStaging.notifyDepreciated({
|
|
1891
|
+
heading: 'shadows="soft" is deprecated',
|
|
1892
|
+
body: "Three has depreciated soft and improved basic PCFShadows, we converted for you.",
|
|
1893
|
+
link: "https://github.com/mrdoob/three.js/wiki/Migration-Guide?utm_source=chatgpt.com#181--182"
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
const types = {
|
|
1897
|
+
basic: three.BasicShadowMap,
|
|
1898
|
+
percentage: three.PCFShadowMap,
|
|
1899
|
+
soft: three.PCFShadowMap,
|
|
1900
|
+
variance: three.VSMShadowMap
|
|
1901
|
+
};
|
|
1902
|
+
renderer.shadowMap.type = types[shadows] ?? three.PCFShadowMap;
|
|
1903
|
+
} else if (is.obj(shadows)) {
|
|
1904
|
+
Object.assign(renderer.shadowMap, shadows);
|
|
1905
|
+
}
|
|
1906
|
+
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
1907
|
+
renderer.shadowMap.needsUpdate = true;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
if (!configured && !borrowsRenderer) {
|
|
1911
|
+
renderer.outputColorSpace = three.SRGBColorSpace;
|
|
1912
|
+
renderer.toneMapping = three.ACESFilmicToneMapping;
|
|
1913
|
+
}
|
|
1914
|
+
const textureColorSpace = requestedTextureColorSpace ?? three.SRGBColorSpace;
|
|
1915
|
+
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
1916
|
+
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
1917
|
+
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
1918
|
+
}
|
|
1919
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && changed("gl")) {
|
|
1920
|
+
const glProps = {};
|
|
1921
|
+
for (const key in glConfig) {
|
|
1922
|
+
if (!NON_APPLIED_RENDERER_PROPS.has(key)) glProps[key] = glConfig[key];
|
|
1923
|
+
}
|
|
1924
|
+
applyProps(renderer, glProps);
|
|
1925
|
+
}
|
|
1926
|
+
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer && !borrowsRenderer) {
|
|
1927
|
+
const currentRenderer = state.renderer;
|
|
1928
|
+
if (changed("renderer")) {
|
|
1929
|
+
const rendererProps = {};
|
|
1930
|
+
for (const key in rendererConfig) {
|
|
1931
|
+
if (!NON_APPLIED_RENDERER_PROPS.has(key)) rendererProps[key] = rendererConfig[key];
|
|
1932
|
+
}
|
|
1933
|
+
applyProps(currentRenderer, rendererProps);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
configured = true;
|
|
1937
|
+
previous = next;
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
const version = "10.0.0-alpha.5";
|
|
1942
|
+
const packageData = {
|
|
1943
|
+
version: version};
|
|
1944
|
+
|
|
1945
|
+
function $1(Ut) {
|
|
1946
|
+
return Ut && Ut.__esModule && Object.prototype.hasOwnProperty.call(Ut, "default") ? Ut.default : Ut;
|
|
1947
|
+
}
|
|
1948
|
+
var S0 = { exports: {} }, Ob = { exports: {} }, P1;
|
|
1949
|
+
function Q1() {
|
|
1950
|
+
return P1 || (P1 = 1, (function(Ut) {
|
|
1951
|
+
Ut.exports = function(m) {
|
|
1952
|
+
function et(t, r, a, l) {
|
|
1953
|
+
return new Fe(t, r, a, l);
|
|
1954
|
+
}
|
|
1955
|
+
function zf() {
|
|
1956
|
+
}
|
|
1957
|
+
function F(t) {
|
|
1958
|
+
var r = "https://react.dev/errors/" + t;
|
|
1959
|
+
if (1 < arguments.length) {
|
|
1960
|
+
r += "?args[]=" + encodeURIComponent(arguments[1]);
|
|
1961
|
+
for (var a = 2; a < arguments.length; a++) r += "&args[]=" + encodeURIComponent(arguments[a]);
|
|
1962
|
+
}
|
|
1963
|
+
return "Minified React error #" + t + "; visit " + r + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";
|
|
1964
|
+
}
|
|
1965
|
+
function Ef(t) {
|
|
1966
|
+
for (var r = t, a = r; a && !a.alternate; ) r = a, (r.flags & 4098) !== 0 && (t = r.return), a = r.return;
|
|
1967
|
+
for (; r.return; ) r = r.return;
|
|
1968
|
+
return r.tag === 3 ? t : null;
|
|
1969
|
+
}
|
|
1970
|
+
function pc(t) {
|
|
1971
|
+
if (Ef(t) !== t) throw Error(F(188));
|
|
1972
|
+
}
|
|
1973
|
+
function hc(t) {
|
|
1974
|
+
var r = t.alternate;
|
|
1975
|
+
if (!r) {
|
|
1976
|
+
if (r = Ef(t), r === null) throw Error(F(188));
|
|
1977
|
+
return r !== t ? null : t;
|
|
1978
|
+
}
|
|
1979
|
+
for (var a = t, l = r; ; ) {
|
|
1980
|
+
var c = a.return;
|
|
1981
|
+
if (c === null) break;
|
|
1982
|
+
var d = c.alternate;
|
|
1983
|
+
if (d === null) {
|
|
1984
|
+
if (l = c.return, l !== null) {
|
|
1985
|
+
a = l;
|
|
1986
|
+
continue;
|
|
1987
|
+
}
|
|
1988
|
+
break;
|
|
1989
|
+
}
|
|
1990
|
+
if (c.child === d.child) {
|
|
1991
|
+
for (d = c.child; d; ) {
|
|
1992
|
+
if (d === a) return pc(c), t;
|
|
1993
|
+
if (d === l) return pc(c), r;
|
|
1994
|
+
d = d.sibling;
|
|
1995
|
+
}
|
|
1996
|
+
throw Error(F(188));
|
|
1997
|
+
}
|
|
1998
|
+
if (a.return !== l.return) a = c, l = d;
|
|
1999
|
+
else {
|
|
2000
|
+
for (var h = false, y = c.child; y; ) {
|
|
2001
|
+
if (y === a) {
|
|
2002
|
+
h = true, a = c, l = d;
|
|
2003
|
+
break;
|
|
2004
|
+
}
|
|
2005
|
+
if (y === l) {
|
|
2006
|
+
h = true, l = c, a = d;
|
|
2007
|
+
break;
|
|
2008
|
+
}
|
|
2009
|
+
y = y.sibling;
|
|
2010
|
+
}
|
|
2011
|
+
if (!h) {
|
|
2012
|
+
for (y = d.child; y; ) {
|
|
2013
|
+
if (y === a) {
|
|
2014
|
+
h = true, a = d, l = c;
|
|
2015
|
+
break;
|
|
2016
|
+
}
|
|
2017
|
+
if (y === l) {
|
|
2018
|
+
h = true, l = d, a = c;
|
|
2019
|
+
break;
|
|
2020
|
+
}
|
|
2021
|
+
y = y.sibling;
|
|
2022
|
+
}
|
|
2023
|
+
if (!h) throw Error(F(189));
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
if (a.alternate !== l) throw Error(F(190));
|
|
2027
|
+
}
|
|
2028
|
+
if (a.tag !== 3) throw Error(F(188));
|
|
2029
|
+
return a.stateNode.current === a ? t : r;
|
|
2030
|
+
}
|
|
2031
|
+
function mc(t) {
|
|
2032
|
+
var r = t.tag;
|
|
2033
|
+
if (r === 5 || r === 26 || r === 27 || r === 6) return t;
|
|
2034
|
+
for (t = t.child; t !== null; ) {
|
|
2035
|
+
if (r = mc(t), r !== null) return r;
|
|
2036
|
+
t = t.sibling;
|
|
2037
|
+
}
|
|
2038
|
+
return null;
|
|
2039
|
+
}
|
|
2040
|
+
function ht(t) {
|
|
2041
|
+
var r = t.tag;
|
|
1246
2042
|
if (r === 5 || r === 26 || r === 27 || r === 6) return t;
|
|
1247
2043
|
for (t = t.child; t !== null; ) {
|
|
1248
2044
|
if (t.tag !== 4 && (r = ht(t), r !== null)) return r;
|
|
@@ -13340,15 +14136,16 @@ function swapInteractivity(store, object, newObject) {
|
|
|
13340
14136
|
pointerState.hovered.set(makeId(next), next);
|
|
13341
14137
|
}
|
|
13342
14138
|
});
|
|
13343
|
-
const captureData
|
|
13344
|
-
|
|
13345
|
-
|
|
13346
|
-
pointerState.captured.
|
|
14139
|
+
for (const [key, captureData] of Array.from(pointerState.captured)) {
|
|
14140
|
+
const { intersection } = captureData;
|
|
14141
|
+
if (key !== object && intersection.object !== object && intersection.eventObject !== object) continue;
|
|
14142
|
+
if (key === object) pointerState.captured.delete(key);
|
|
14143
|
+
pointerState.captured.set(key === object ? newObject : key, {
|
|
13347
14144
|
...captureData,
|
|
13348
14145
|
intersection: {
|
|
13349
|
-
...
|
|
13350
|
-
object:
|
|
13351
|
-
eventObject:
|
|
14146
|
+
...intersection,
|
|
14147
|
+
object: intersection.object === object ? newObject : intersection.object,
|
|
14148
|
+
eventObject: intersection.eventObject === object ? newObject : intersection.eventObject
|
|
13352
14149
|
}
|
|
13353
14150
|
});
|
|
13354
14151
|
}
|
|
@@ -13877,10 +14674,11 @@ const catalogue = globalThis[R3F_CATALOGUE] ?? (globalThis[R3F_CATALOGUE] = {});
|
|
|
13877
14674
|
const R3F_EXTEND_ID = Symbol.for("@react-three/fiber.extendId");
|
|
13878
14675
|
const ids = globalThis;
|
|
13879
14676
|
const toPascalCase = (type) => `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
13880
|
-
const isConstructor = (object) => typeof object === "function";
|
|
14677
|
+
const isConstructor$1 = (object) => typeof object === "function";
|
|
13881
14678
|
function extend(objects) {
|
|
13882
|
-
if (isConstructor(objects)) {
|
|
13883
|
-
|
|
14679
|
+
if (isConstructor$1(objects)) {
|
|
14680
|
+
let id = ids[R3F_EXTEND_ID] ?? 0;
|
|
14681
|
+
while (`${id}` in catalogue) id++;
|
|
13884
14682
|
ids[R3F_EXTEND_ID] = id + 1;
|
|
13885
14683
|
const Component = `${id}`;
|
|
13886
14684
|
catalogue[Component] = objects;
|
|
@@ -13888,15 +14686,14 @@ function extend(objects) {
|
|
|
13888
14686
|
} else {
|
|
13889
14687
|
for (const name in objects) {
|
|
13890
14688
|
const object = objects[name];
|
|
13891
|
-
if (isConstructor(object)) catalogue[name] = object;
|
|
14689
|
+
if (isConstructor$1(object)) catalogue[name] = object;
|
|
13892
14690
|
}
|
|
13893
14691
|
}
|
|
13894
14692
|
}
|
|
13895
|
-
|
|
13896
14693
|
function resolveConstructor(name, root) {
|
|
13897
14694
|
if (Object.prototype.hasOwnProperty.call(catalogue, name)) return catalogue[name];
|
|
13898
14695
|
const object = root.getState().internal.support?.three[name];
|
|
13899
|
-
return isConstructor(object) ? object : void 0;
|
|
14696
|
+
return isConstructor$1(object) ? object : void 0;
|
|
13900
14697
|
}
|
|
13901
14698
|
|
|
13902
14699
|
function createReconciler(config) {
|
|
@@ -13933,6 +14730,7 @@ function hideInstance(instance) {
|
|
|
13933
14730
|
if (instance.props.attach && instance.parent?.object) {
|
|
13934
14731
|
detach(instance.parent, instance);
|
|
13935
14732
|
} else if (isObject3D(instance.object)) {
|
|
14733
|
+
instance.previousVisible = instance.object.visible;
|
|
13936
14734
|
instance.object.visible = false;
|
|
13937
14735
|
}
|
|
13938
14736
|
instance.isHidden = true;
|
|
@@ -13943,9 +14741,10 @@ function unhideInstance(instance) {
|
|
|
13943
14741
|
if (instance.isHidden) {
|
|
13944
14742
|
if (instance.props.attach && instance.parent?.object) {
|
|
13945
14743
|
attach(instance.parent, instance);
|
|
13946
|
-
} else if (isObject3D(instance.object)
|
|
13947
|
-
instance.object.visible = true;
|
|
14744
|
+
} else if (isObject3D(instance.object)) {
|
|
14745
|
+
instance.object.visible = instance.previousVisible ?? true;
|
|
13948
14746
|
}
|
|
14747
|
+
instance.previousVisible = void 0;
|
|
13949
14748
|
instance.isHidden = false;
|
|
13950
14749
|
invalidateInstance(instance);
|
|
13951
14750
|
}
|
|
@@ -14018,6 +14817,7 @@ function disposeOnIdle(object) {
|
|
|
14018
14817
|
}
|
|
14019
14818
|
function removeChild(parent, child, dispose) {
|
|
14020
14819
|
if (!child) return;
|
|
14820
|
+
const wasLinked = !!child.parent;
|
|
14021
14821
|
child.parent = null;
|
|
14022
14822
|
const childIndex = parent.children.indexOf(child);
|
|
14023
14823
|
if (childIndex !== -1) parent.children.splice(childIndex, 1);
|
|
@@ -14037,7 +14837,10 @@ function removeChild(parent, child, dispose) {
|
|
|
14037
14837
|
if (shouldDispose && child.type !== "primitive" && child.object.type !== "Scene") {
|
|
14038
14838
|
disposeOnIdle(child.object);
|
|
14039
14839
|
}
|
|
14040
|
-
if (dispose === void 0)
|
|
14840
|
+
if (dispose === void 0 && wasLinked) {
|
|
14841
|
+
const state = findInitialRoot(child).getState();
|
|
14842
|
+
if (state.internal.active && state.internal.frames === 0) state.invalidate();
|
|
14843
|
+
}
|
|
14041
14844
|
}
|
|
14042
14845
|
function setFiberRef(fiber, publicInstance) {
|
|
14043
14846
|
for (const _fiber of [fiber, fiber.alternate]) {
|
|
@@ -14348,472 +15151,135 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14348
15151
|
},
|
|
14349
15152
|
resolveUpdatePriority() {
|
|
14350
15153
|
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
14351
|
-
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
14352
|
-
if (eventType === void 0) return r;
|
|
14353
|
-
return getEventPriority(eventType);
|
|
14354
|
-
},
|
|
14355
|
-
resetFormInstance() {
|
|
14356
|
-
},
|
|
14357
|
-
// @ts-ignore DefinitelyTyped is not up to date
|
|
14358
|
-
rendererPackageName: "@react-three/fiber",
|
|
14359
|
-
rendererVersion: packageData.version,
|
|
14360
|
-
// 19.2 Reconciler
|
|
14361
|
-
// https://github.com/facebook/react/pull/31975
|
|
14362
|
-
// https://github.com/facebook/react/pull/31999
|
|
14363
|
-
applyViewTransitionName(_instance, _name, _className) {
|
|
14364
|
-
},
|
|
14365
|
-
restoreViewTransitionName(_instance, _props) {
|
|
14366
|
-
},
|
|
14367
|
-
cancelViewTransitionName(_instance, _name, _props) {
|
|
14368
|
-
},
|
|
14369
|
-
cancelRootViewTransitionName(_rootContainer) {
|
|
14370
|
-
},
|
|
14371
|
-
restoreRootViewTransitionName(_rootContainer) {
|
|
14372
|
-
},
|
|
14373
|
-
InstanceMeasurement: null,
|
|
14374
|
-
measureInstance: (_instance) => null,
|
|
14375
|
-
wasInstanceInViewport: (_measurement) => true,
|
|
14376
|
-
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
14377
|
-
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
14378
|
-
// https://github.com/facebook/react/pull/32002
|
|
14379
|
-
// https://github.com/facebook/react/pull/34486
|
|
14380
|
-
suspendOnActiveViewTransition(_state, _container) {
|
|
14381
|
-
},
|
|
14382
|
-
// https://github.com/facebook/react/pull/32451
|
|
14383
|
-
// https://github.com/facebook/react/pull/32760
|
|
14384
|
-
// React hands the whole commit to the host when a transition touches a <ViewTransition> subtree.
|
|
14385
|
-
// three.js has nothing to animate between commits, so this mirrors the react-dom fallback for
|
|
14386
|
-
// browsers without document.startViewTransition and flushes the commit synchronously.
|
|
14387
|
-
startViewTransition(_suspendedState, _rootContainer, _transitionTypes, mutationCallback, layoutCallback, _afterMutationCallback, spawnedWorkCallback, _passiveCallback, _errorCallback, _blockedCallback, finishedAnimation) {
|
|
14388
|
-
mutationCallback();
|
|
14389
|
-
layoutCallback();
|
|
14390
|
-
finishedAnimation?.();
|
|
14391
|
-
spawnedWorkCallback();
|
|
14392
|
-
return null;
|
|
14393
|
-
},
|
|
14394
|
-
startGestureTransition(_suspendedState, _rootContainer, _timeline, _rangeStart, _rangeEnd, _transitionTypes, mutationCallback, animateCallback, _errorCallback, finishedAnimation) {
|
|
14395
|
-
mutationCallback();
|
|
14396
|
-
animateCallback();
|
|
14397
|
-
finishedAnimation?.();
|
|
14398
|
-
return null;
|
|
14399
|
-
},
|
|
14400
|
-
stopViewTransition(_transition) {
|
|
14401
|
-
},
|
|
14402
|
-
// https://github.com/facebook/react/pull/35564
|
|
14403
|
-
// Only reached with a non-null transition from startViewTransition, which never returns one here
|
|
14404
|
-
addViewTransitionFinishedListener(_transition, callback) {
|
|
14405
|
-
callback();
|
|
14406
|
-
},
|
|
14407
|
-
// https://github.com/facebook/react/pull/32038
|
|
14408
|
-
createViewTransitionInstance: (_name) => null,
|
|
14409
|
-
// https://github.com/facebook/react/pull/32379
|
|
14410
|
-
// https://github.com/facebook/react/pull/32786
|
|
14411
|
-
getCurrentGestureOffset(_provider) {
|
|
14412
|
-
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
14413
|
-
},
|
|
14414
|
-
// https://github.com/facebook/react/pull/32500
|
|
14415
|
-
cloneMutableInstance(instance, _keepChildren) {
|
|
14416
|
-
return instance;
|
|
14417
|
-
},
|
|
14418
|
-
cloneMutableTextInstance(textInstance) {
|
|
14419
|
-
return textInstance;
|
|
14420
|
-
},
|
|
14421
|
-
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
14422
|
-
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
14423
|
-
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
14424
|
-
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
14425
|
-
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
14426
|
-
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
14427
|
-
cloneRootViewTransitionContainer(_rootContainer) {
|
|
14428
|
-
},
|
|
14429
|
-
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
14430
|
-
},
|
|
14431
|
-
// https://github.com/facebook/react/pull/32465
|
|
14432
|
-
createFragmentInstance: (_fiber) => null,
|
|
14433
|
-
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
14434
|
-
},
|
|
14435
|
-
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
14436
|
-
},
|
|
14437
|
-
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
14438
|
-
},
|
|
14439
|
-
// https://github.com/facebook/react/pull/32653
|
|
14440
|
-
measureClonedInstance: (_instance) => null,
|
|
14441
|
-
// https://github.com/facebook/react/pull/32819
|
|
14442
|
-
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
14443
|
-
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
14444
|
-
// https://github.com/facebook/react/pull/34486
|
|
14445
|
-
startSuspendingCommit: () => null,
|
|
14446
|
-
// https://github.com/facebook/react/pull/34522
|
|
14447
|
-
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14448
|
-
});
|
|
14449
|
-
|
|
14450
|
-
|
|
14451
|
-
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
14452
|
-
if (!stack) return false;
|
|
14453
|
-
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
14454
|
-
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
14455
|
-
}
|
|
14456
|
-
|
|
14457
|
-
const createStore = (invalidate, advance) => {
|
|
14458
|
-
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
14459
|
-
let position;
|
|
14460
|
-
let defaultTarget;
|
|
14461
|
-
let tempTarget;
|
|
14462
|
-
function getCurrentViewport(camera = get().camera, target = void 0, size = get().size) {
|
|
14463
|
-
const { Vector3 } = getThree();
|
|
14464
|
-
position ?? (position = new Vector3());
|
|
14465
|
-
defaultTarget ?? (defaultTarget = new Vector3());
|
|
14466
|
-
tempTarget ?? (tempTarget = new Vector3());
|
|
14467
|
-
target ?? (target = defaultTarget);
|
|
14468
|
-
const { width, height, top, left } = size;
|
|
14469
|
-
const aspect = width / height;
|
|
14470
|
-
if (target.isVector3) tempTarget.copy(target);
|
|
14471
|
-
else tempTarget.set(...target);
|
|
14472
|
-
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
14473
|
-
if (isOrthographicCamera(camera)) {
|
|
14474
|
-
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
14475
|
-
} else {
|
|
14476
|
-
const fov = camera.fov * Math.PI / 180;
|
|
14477
|
-
const h = 2 * Math.tan(fov / 2) * distance;
|
|
14478
|
-
const w = h * (width / height);
|
|
14479
|
-
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
14480
|
-
}
|
|
14481
|
-
}
|
|
14482
|
-
let performanceTimeout = void 0;
|
|
14483
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
14484
|
-
const rootState = {
|
|
14485
|
-
set,
|
|
14486
|
-
get,
|
|
14487
|
-
// Mock objects that have to be configured
|
|
14488
|
-
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
14489
|
-
primaryStore: null,
|
|
14490
|
-
gl: null,
|
|
14491
|
-
renderer: null,
|
|
14492
|
-
camera: null,
|
|
14493
|
-
// frustum, pointer and mouse are three objects; configure() creates them with the renderer
|
|
14494
|
-
frustum: null,
|
|
14495
|
-
autoUpdateFrustum: true,
|
|
14496
|
-
raycaster: null,
|
|
14497
|
-
events: {
|
|
14498
|
-
priority: 1,
|
|
14499
|
-
enabled: true,
|
|
14500
|
-
connected: false,
|
|
14501
|
-
frameTimedRaycasts: true,
|
|
14502
|
-
alwaysFireOnScroll: true,
|
|
14503
|
-
updateOnFrame: false
|
|
14504
|
-
},
|
|
14505
|
-
scene: null,
|
|
14506
|
-
rootScene: null,
|
|
14507
|
-
xr: null,
|
|
14508
|
-
inspector: null,
|
|
14509
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
14510
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
14511
|
-
textureColorSpace: "srgb",
|
|
14512
|
-
// THREE.SRGBColorSpace
|
|
14513
|
-
isLegacy: false,
|
|
14514
|
-
webGPUSupported: false,
|
|
14515
|
-
isNative: false,
|
|
14516
|
-
controls: null,
|
|
14517
|
-
pointer: null,
|
|
14518
|
-
mouse: null,
|
|
14519
|
-
frameloop: "always",
|
|
14520
|
-
onPointerMissed: void 0,
|
|
14521
|
-
onDragOverMissed: void 0,
|
|
14522
|
-
onDropMissed: void 0,
|
|
14523
|
-
performance: {
|
|
14524
|
-
current: 1,
|
|
14525
|
-
min: 0.5,
|
|
14526
|
-
max: 1,
|
|
14527
|
-
debounce: 200,
|
|
14528
|
-
regress: () => {
|
|
14529
|
-
const state2 = get();
|
|
14530
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
14531
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
14532
|
-
performanceTimeout = setTimeout(
|
|
14533
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
14534
|
-
state2.performance.debounce
|
|
14535
|
-
);
|
|
14536
|
-
}
|
|
14537
|
-
},
|
|
14538
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
14539
|
-
viewport: {
|
|
14540
|
-
initialDpr: 0,
|
|
14541
|
-
dpr: 0,
|
|
14542
|
-
width: 0,
|
|
14543
|
-
height: 0,
|
|
14544
|
-
top: 0,
|
|
14545
|
-
left: 0,
|
|
14546
|
-
aspect: 0,
|
|
14547
|
-
distance: 0,
|
|
14548
|
-
factor: 0,
|
|
14549
|
-
getCurrentViewport
|
|
14550
|
-
},
|
|
14551
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
14552
|
-
setSize: (width, height, top, left) => {
|
|
14553
|
-
const state2 = get();
|
|
14554
|
-
if (width === void 0) {
|
|
14555
|
-
set({ _sizeImperative: false });
|
|
14556
|
-
if (state2._sizeProps) {
|
|
14557
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
14558
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
14559
|
-
const currentSize = state2.size;
|
|
14560
|
-
const newSize = {
|
|
14561
|
-
width: propW ?? currentSize.width,
|
|
14562
|
-
height: propH ?? currentSize.height,
|
|
14563
|
-
top: currentSize.top,
|
|
14564
|
-
left: currentSize.left
|
|
14565
|
-
};
|
|
14566
|
-
set((s) => ({
|
|
14567
|
-
size: newSize,
|
|
14568
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
14569
|
-
}));
|
|
14570
|
-
get().invalidate();
|
|
14571
|
-
}
|
|
14572
|
-
}
|
|
14573
|
-
return;
|
|
14574
|
-
}
|
|
14575
|
-
const w = width;
|
|
14576
|
-
const h = height ?? width;
|
|
14577
|
-
const t = top ?? state2.size.top;
|
|
14578
|
-
const l = left ?? state2.size.left;
|
|
14579
|
-
const size = { width: w, height: h, top: t, left: l };
|
|
14580
|
-
set((s) => ({
|
|
14581
|
-
size,
|
|
14582
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
14583
|
-
_sizeImperative: true
|
|
14584
|
-
}));
|
|
14585
|
-
get().invalidate();
|
|
14586
|
-
},
|
|
14587
|
-
setDpr: (dpr) => set((state2) => {
|
|
14588
|
-
const resolved = calculateDpr(dpr);
|
|
14589
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
14590
|
-
}),
|
|
14591
|
-
setFrameloop: (frameloop = "always") => {
|
|
14592
|
-
const rootId = get().internal.rootId;
|
|
14593
|
-
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
14594
|
-
set(() => ({ frameloop }));
|
|
14595
|
-
},
|
|
14596
|
-
setError: (error) => set(() => ({ error })),
|
|
14597
|
-
error: null,
|
|
14598
|
-
//* Texture registry (useTextures) ==============================
|
|
14599
|
-
// TSL fields (uniforms, nodes, ..., renderPipeline) are added by @react-three/tsl's root extension.
|
|
14600
|
-
textures: /* @__PURE__ */ new Map(),
|
|
14601
|
-
_textureRefs: /* @__PURE__ */ new Map(),
|
|
14602
|
-
_sizeImperative: false,
|
|
14603
|
-
_sizeProps: null,
|
|
14604
|
-
previousRoot: void 0,
|
|
14605
|
-
internal: {
|
|
14606
|
-
// Events
|
|
14607
|
-
interaction: [],
|
|
14608
|
-
subscribers: [],
|
|
14609
|
-
// Per-pointer state (new unified structure)
|
|
14610
|
-
pointerMap: /* @__PURE__ */ new Map(),
|
|
14611
|
-
pointerDirty: /* @__PURE__ */ new Map(),
|
|
14612
|
-
lastEvent: React__namespace.createRef(),
|
|
14613
|
-
// Deprecated but kept for backwards compatibility
|
|
14614
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
14615
|
-
initialClick: [0, 0],
|
|
14616
|
-
initialHits: [],
|
|
14617
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
14618
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
14619
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
14620
|
-
// Occlusion system (WebGPU only)
|
|
14621
|
-
occlusionEnabled: false,
|
|
14622
|
-
occlusionObserver: null,
|
|
14623
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
14624
|
-
helperGroup: null,
|
|
14625
|
-
// Updates
|
|
14626
|
-
active: false,
|
|
14627
|
-
frames: 0,
|
|
14628
|
-
priority: 0,
|
|
14629
|
-
subscribe: (ref, priority, store) => {
|
|
14630
|
-
const internal = get().internal;
|
|
14631
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
14632
|
-
internal.subscribers.push({ ref, priority, store });
|
|
14633
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14634
|
-
return () => {
|
|
14635
|
-
const internal2 = get().internal;
|
|
14636
|
-
if (internal2?.subscribers) {
|
|
14637
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14638
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14639
|
-
}
|
|
14640
|
-
};
|
|
14641
|
-
},
|
|
14642
|
-
// Renderer Storage (single source of truth)
|
|
14643
|
-
actualRenderer: null,
|
|
14644
|
-
// The renderer support configure() loads for this root
|
|
14645
|
-
support: null,
|
|
14646
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14647
|
-
scheduler: null,
|
|
14648
|
-
// Replaces the default render call when set (see setRenderOverride)
|
|
14649
|
-
renderOverride: null
|
|
14650
|
-
}
|
|
14651
|
-
};
|
|
14652
|
-
return rootState;
|
|
14653
|
-
});
|
|
14654
|
-
const state = rootStore.getState();
|
|
14655
|
-
Object.defineProperty(state, "gl", {
|
|
14656
|
-
get() {
|
|
14657
|
-
const currentState = rootStore.getState();
|
|
14658
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14659
|
-
const stack = new Error().stack || "";
|
|
14660
|
-
if (!isInternalRendererAccess(stack)) {
|
|
14661
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14662
|
-
extensions.notifyDepreciated({
|
|
14663
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
14664
|
-
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
|
|
14665
|
-
});
|
|
14666
|
-
}
|
|
14667
|
-
}
|
|
14668
|
-
return currentState.internal.actualRenderer;
|
|
14669
|
-
},
|
|
14670
|
-
set(value) {
|
|
14671
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
14672
|
-
},
|
|
14673
|
-
enumerable: true,
|
|
14674
|
-
configurable: true
|
|
14675
|
-
});
|
|
14676
|
-
Object.defineProperty(state, "renderer", {
|
|
14677
|
-
get() {
|
|
14678
|
-
return rootStore.getState().internal.actualRenderer;
|
|
14679
|
-
},
|
|
14680
|
-
set(value) {
|
|
14681
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
14682
|
-
},
|
|
14683
|
-
enumerable: true,
|
|
14684
|
-
configurable: true
|
|
14685
|
-
});
|
|
14686
|
-
let oldScene = state.scene;
|
|
14687
|
-
rootStore.subscribe(() => {
|
|
14688
|
-
const currentState = rootStore.getState();
|
|
14689
|
-
const { scene, rootScene, set } = currentState;
|
|
14690
|
-
if (scene !== oldScene) {
|
|
14691
|
-
oldScene = scene;
|
|
14692
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
14693
|
-
set({ rootScene: scene });
|
|
14694
|
-
}
|
|
14695
|
-
}
|
|
14696
|
-
});
|
|
14697
|
-
let oldSize = state.size;
|
|
14698
|
-
let oldDpr = state.viewport.dpr;
|
|
14699
|
-
let oldCamera = state.camera;
|
|
14700
|
-
rootStore.subscribe(() => {
|
|
14701
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14702
|
-
const actualRenderer = internal.actualRenderer;
|
|
14703
|
-
const canvasTarget = internal.canvasTarget;
|
|
14704
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14705
|
-
oldSize = size;
|
|
14706
|
-
oldDpr = viewport.dpr;
|
|
14707
|
-
updateCamera(camera, size);
|
|
14708
|
-
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14709
|
-
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14710
|
-
resizeTarget.setSize(size.width, size.height, false);
|
|
14711
|
-
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14712
|
-
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
14713
|
-
}
|
|
14714
|
-
if (camera !== oldCamera) {
|
|
14715
|
-
oldCamera = camera;
|
|
14716
|
-
const { rootScene } = rootStore.getState();
|
|
14717
|
-
if (camera && rootScene && !camera.parent) {
|
|
14718
|
-
rootScene.add(camera);
|
|
14719
|
-
}
|
|
14720
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14721
|
-
const currentState = rootStore.getState();
|
|
14722
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
14723
|
-
updateFrustum(camera, currentState.frustum);
|
|
14724
|
-
}
|
|
14725
|
-
}
|
|
14726
|
-
});
|
|
14727
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
14728
|
-
return rootStore;
|
|
14729
|
-
};
|
|
14730
|
-
|
|
14731
|
-
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
14732
|
-
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
14733
|
-
function registerPrimary(id, renderer, store) {
|
|
14734
|
-
if (primaryRegistry.has(id)) {
|
|
14735
|
-
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
14736
|
-
}
|
|
14737
|
-
const entry = { renderer, store };
|
|
14738
|
-
primaryRegistry.set(id, entry);
|
|
14739
|
-
const subscribers = pendingSubscribers.get(id);
|
|
14740
|
-
if (subscribers) {
|
|
14741
|
-
subscribers.forEach((callback) => callback(entry));
|
|
14742
|
-
pendingSubscribers.delete(id);
|
|
14743
|
-
}
|
|
14744
|
-
return () => {
|
|
14745
|
-
const currentEntry = primaryRegistry.get(id);
|
|
14746
|
-
if (currentEntry?.renderer === renderer) {
|
|
14747
|
-
primaryRegistry.delete(id);
|
|
14748
|
-
}
|
|
14749
|
-
};
|
|
14750
|
-
}
|
|
14751
|
-
function getPrimary(id) {
|
|
14752
|
-
return primaryRegistry.get(id);
|
|
14753
|
-
}
|
|
14754
|
-
function waitForPrimary(id, timeout = 5e3) {
|
|
14755
|
-
const existing = primaryRegistry.get(id);
|
|
14756
|
-
if (existing) {
|
|
14757
|
-
return Promise.resolve(existing);
|
|
14758
|
-
}
|
|
14759
|
-
return new Promise((resolve, reject) => {
|
|
14760
|
-
const timeoutId = setTimeout(() => {
|
|
14761
|
-
const subscribers = pendingSubscribers.get(id);
|
|
14762
|
-
if (subscribers) {
|
|
14763
|
-
const index = subscribers.indexOf(callback);
|
|
14764
|
-
if (index !== -1) subscribers.splice(index, 1);
|
|
14765
|
-
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
14766
|
-
}
|
|
14767
|
-
reject(new Error(`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}"> is mounted.`));
|
|
14768
|
-
}, timeout);
|
|
14769
|
-
const callback = (entry) => {
|
|
14770
|
-
clearTimeout(timeoutId);
|
|
14771
|
-
resolve(entry);
|
|
14772
|
-
};
|
|
14773
|
-
if (!pendingSubscribers.has(id)) {
|
|
14774
|
-
pendingSubscribers.set(id, []);
|
|
14775
|
-
}
|
|
14776
|
-
pendingSubscribers.get(id).push(callback);
|
|
14777
|
-
});
|
|
14778
|
-
}
|
|
14779
|
-
function hasPrimary(id) {
|
|
14780
|
-
return primaryRegistry.has(id);
|
|
14781
|
-
}
|
|
14782
|
-
function unregisterPrimary(id) {
|
|
14783
|
-
primaryRegistry.delete(id);
|
|
14784
|
-
}
|
|
14785
|
-
function getPrimaryIds() {
|
|
14786
|
-
return Array.from(primaryRegistry.keys());
|
|
15154
|
+
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
15155
|
+
if (eventType === void 0) return r;
|
|
15156
|
+
return getEventPriority(eventType);
|
|
15157
|
+
},
|
|
15158
|
+
resetFormInstance() {
|
|
15159
|
+
},
|
|
15160
|
+
// @ts-ignore DefinitelyTyped is not up to date
|
|
15161
|
+
rendererPackageName: "@react-three/fiber",
|
|
15162
|
+
rendererVersion: packageData.version,
|
|
15163
|
+
// 19.2 Reconciler
|
|
15164
|
+
// https://github.com/facebook/react/pull/31975
|
|
15165
|
+
// https://github.com/facebook/react/pull/31999
|
|
15166
|
+
applyViewTransitionName(_instance, _name, _className) {
|
|
15167
|
+
},
|
|
15168
|
+
restoreViewTransitionName(_instance, _props) {
|
|
15169
|
+
},
|
|
15170
|
+
cancelViewTransitionName(_instance, _name, _props) {
|
|
15171
|
+
},
|
|
15172
|
+
cancelRootViewTransitionName(_rootContainer) {
|
|
15173
|
+
},
|
|
15174
|
+
restoreRootViewTransitionName(_rootContainer) {
|
|
15175
|
+
},
|
|
15176
|
+
InstanceMeasurement: null,
|
|
15177
|
+
measureInstance: (_instance) => null,
|
|
15178
|
+
wasInstanceInViewport: (_measurement) => true,
|
|
15179
|
+
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
15180
|
+
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
15181
|
+
// https://github.com/facebook/react/pull/32002
|
|
15182
|
+
// https://github.com/facebook/react/pull/34486
|
|
15183
|
+
suspendOnActiveViewTransition(_state, _container) {
|
|
15184
|
+
},
|
|
15185
|
+
// https://github.com/facebook/react/pull/32451
|
|
15186
|
+
// https://github.com/facebook/react/pull/32760
|
|
15187
|
+
// React hands the whole commit to the host when a transition touches a <ViewTransition> subtree.
|
|
15188
|
+
// three.js has nothing to animate between commits, so this mirrors the react-dom fallback for
|
|
15189
|
+
// browsers without document.startViewTransition and flushes the commit synchronously.
|
|
15190
|
+
startViewTransition(_suspendedState, _rootContainer, _transitionTypes, mutationCallback, layoutCallback, _afterMutationCallback, spawnedWorkCallback, _passiveCallback, _errorCallback, _blockedCallback, finishedAnimation) {
|
|
15191
|
+
mutationCallback();
|
|
15192
|
+
layoutCallback();
|
|
15193
|
+
finishedAnimation?.();
|
|
15194
|
+
spawnedWorkCallback();
|
|
15195
|
+
return null;
|
|
15196
|
+
},
|
|
15197
|
+
startGestureTransition(_suspendedState, _rootContainer, _timeline, _rangeStart, _rangeEnd, _transitionTypes, mutationCallback, animateCallback, _errorCallback, finishedAnimation) {
|
|
15198
|
+
mutationCallback();
|
|
15199
|
+
animateCallback();
|
|
15200
|
+
finishedAnimation?.();
|
|
15201
|
+
return null;
|
|
15202
|
+
},
|
|
15203
|
+
stopViewTransition(_transition) {
|
|
15204
|
+
},
|
|
15205
|
+
// https://github.com/facebook/react/pull/35564
|
|
15206
|
+
// Only reached with a non-null transition from startViewTransition, which never returns one here
|
|
15207
|
+
addViewTransitionFinishedListener(_transition, callback) {
|
|
15208
|
+
callback();
|
|
15209
|
+
},
|
|
15210
|
+
// https://github.com/facebook/react/pull/32038
|
|
15211
|
+
createViewTransitionInstance: (_name) => null,
|
|
15212
|
+
// https://github.com/facebook/react/pull/32379
|
|
15213
|
+
// https://github.com/facebook/react/pull/32786
|
|
15214
|
+
getCurrentGestureOffset(_provider) {
|
|
15215
|
+
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
15216
|
+
},
|
|
15217
|
+
// https://github.com/facebook/react/pull/32500
|
|
15218
|
+
cloneMutableInstance(instance, _keepChildren) {
|
|
15219
|
+
return instance;
|
|
15220
|
+
},
|
|
15221
|
+
cloneMutableTextInstance(textInstance) {
|
|
15222
|
+
return textInstance;
|
|
15223
|
+
},
|
|
15224
|
+
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
15225
|
+
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
15226
|
+
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
15227
|
+
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
15228
|
+
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
15229
|
+
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
15230
|
+
cloneRootViewTransitionContainer(_rootContainer) {
|
|
15231
|
+
},
|
|
15232
|
+
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
15233
|
+
},
|
|
15234
|
+
// https://github.com/facebook/react/pull/32465
|
|
15235
|
+
createFragmentInstance: (_fiber) => null,
|
|
15236
|
+
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
15237
|
+
},
|
|
15238
|
+
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
15239
|
+
},
|
|
15240
|
+
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
15241
|
+
},
|
|
15242
|
+
// https://github.com/facebook/react/pull/32653
|
|
15243
|
+
measureClonedInstance: (_instance) => null,
|
|
15244
|
+
// https://github.com/facebook/react/pull/32819
|
|
15245
|
+
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
15246
|
+
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
15247
|
+
// https://github.com/facebook/react/pull/34486
|
|
15248
|
+
startSuspendingCommit: () => null,
|
|
15249
|
+
// https://github.com/facebook/react/pull/34522
|
|
15250
|
+
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
15251
|
+
});
|
|
15252
|
+
function flushSync(fn) {
|
|
15253
|
+
return reconciler.flushSyncFromReconciler(fn);
|
|
14787
15254
|
}
|
|
14788
15255
|
|
|
14789
|
-
const
|
|
15256
|
+
const noop = () => {
|
|
15257
|
+
};
|
|
14790
15258
|
const _roots = /* @__PURE__ */ new Map();
|
|
14791
|
-
function
|
|
14792
|
-
const state =
|
|
14793
|
-
|
|
14794
|
-
|
|
14795
|
-
|
|
14796
|
-
|
|
14797
|
-
|
|
14798
|
-
|
|
14799
|
-
|
|
14800
|
-
|
|
14801
|
-
|
|
14802
|
-
|
|
14803
|
-
|
|
14804
|
-
|
|
14805
|
-
|
|
14806
|
-
|
|
14807
|
-
|
|
14808
|
-
|
|
14809
|
-
|
|
14810
|
-
|
|
14811
|
-
|
|
14812
|
-
|
|
14813
|
-
|
|
14814
|
-
};
|
|
15259
|
+
function transitionRoot(root, event) {
|
|
15260
|
+
const state = root.state;
|
|
15261
|
+
switch (event.type) {
|
|
15262
|
+
case "use":
|
|
15263
|
+
if (state.status === "disposed") return false;
|
|
15264
|
+
if (state.status === "closing") {
|
|
15265
|
+
root.store.getState().internal.active = true;
|
|
15266
|
+
state.settle();
|
|
15267
|
+
}
|
|
15268
|
+
root.state = { status: "open" };
|
|
15269
|
+
return true;
|
|
15270
|
+
case "unmount": {
|
|
15271
|
+
if (state.status === "disposed") return false;
|
|
15272
|
+
if (state.status === "closing") state.settle();
|
|
15273
|
+
const { promise, resolve } = deferred();
|
|
15274
|
+
root.state = { status: "closing", token: event.token, settled: promise, settle: resolve };
|
|
15275
|
+
return true;
|
|
15276
|
+
}
|
|
15277
|
+
case "dispose":
|
|
15278
|
+
if (state.status !== "closing" || state.token !== event.token) return false;
|
|
15279
|
+
root.state = { status: "disposed" };
|
|
15280
|
+
state.settle();
|
|
15281
|
+
return true;
|
|
14815
15282
|
}
|
|
14816
|
-
return { width: 0, height: 0, top: 0, left: 0, ...size };
|
|
14817
15283
|
}
|
|
14818
15284
|
function createRoot(canvas, provider) {
|
|
14819
15285
|
const prevRoot = _roots.get(canvas);
|
|
@@ -14851,540 +15317,615 @@ function createRoot(canvas, provider) {
|
|
|
14851
15317
|
null
|
|
14852
15318
|
// transitionCallbacks
|
|
14853
15319
|
);
|
|
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
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
14917
|
-
|
|
14918
|
-
|
|
14919
|
-
|
|
14920
|
-
|
|
14921
|
-
|
|
14922
|
-
|
|
14923
|
-
}
|
|
14924
|
-
|
|
14925
|
-
|
|
14926
|
-
|
|
14927
|
-
|
|
14928
|
-
|
|
14929
|
-
|
|
14930
|
-
|
|
14931
|
-
|
|
14932
|
-
|
|
14933
|
-
|
|
15320
|
+
const root = prevRoot || {
|
|
15321
|
+
fiber,
|
|
15322
|
+
store,
|
|
15323
|
+
state: { status: "open" },
|
|
15324
|
+
ready: fulfilled(void 0),
|
|
15325
|
+
configuration: {}
|
|
15326
|
+
};
|
|
15327
|
+
if (!prevRoot) _roots.set(canvas, root);
|
|
15328
|
+
if (!prevRoot) root.configuration.apply = createRootConfiguration(store, canvas);
|
|
15329
|
+
let mounted = false;
|
|
15330
|
+
return {
|
|
15331
|
+
get ready() {
|
|
15332
|
+
return root.ready;
|
|
15333
|
+
},
|
|
15334
|
+
configure(props = {}) {
|
|
15335
|
+
if (!transitionRoot(root, { type: "use" })) {
|
|
15336
|
+
return rejected(new Error("R3F: Cannot configure a root after it has unmounted (disposal has started)."));
|
|
15337
|
+
}
|
|
15338
|
+
const previous = root.ready;
|
|
15339
|
+
const { promise, resolve, reject } = deferred();
|
|
15340
|
+
root.ready = promise;
|
|
15341
|
+
const run = () => {
|
|
15342
|
+
try {
|
|
15343
|
+
const initialized = initializeRenderer(canvas, provider, store, props);
|
|
15344
|
+
const apply = () => {
|
|
15345
|
+
if (props.id) {
|
|
15346
|
+
for (const other of _roots.values()) {
|
|
15347
|
+
if (other !== root && other.state.status === "closing" && other.store.getState().internal.rootId === props.id) {
|
|
15348
|
+
other.state.settled.then(apply).catch(reject);
|
|
15349
|
+
return;
|
|
15350
|
+
}
|
|
15351
|
+
}
|
|
15352
|
+
}
|
|
15353
|
+
const previous2 = root.configuration.previous;
|
|
15354
|
+
root.configuration.apply(props);
|
|
15355
|
+
configureScheduler(store, props.id, props.scheduler, previous2?.scheduler);
|
|
15356
|
+
textureStaging.attachRootExtensions(store);
|
|
15357
|
+
root.configuration.previous = props;
|
|
15358
|
+
resolve(this);
|
|
15359
|
+
};
|
|
15360
|
+
if (isPromiseLike(initialized)) Promise.resolve(initialized).then(apply).catch(reject);
|
|
15361
|
+
else apply();
|
|
15362
|
+
} catch (error) {
|
|
15363
|
+
reject(error);
|
|
15364
|
+
}
|
|
15365
|
+
};
|
|
15366
|
+
if (previous.status === "pending") previous.then(run, reject);
|
|
15367
|
+
else run();
|
|
15368
|
+
return promise;
|
|
15369
|
+
},
|
|
15370
|
+
render(children) {
|
|
15371
|
+
if (!transitionRoot(root, { type: "use" })) return store;
|
|
15372
|
+
if (!store.getState().internal.actualRenderer && root.ready.status === "fulfilled") this.configure();
|
|
15373
|
+
if (root.ready.status === "rejected") throw root.ready.reason;
|
|
15374
|
+
const commit = () => {
|
|
15375
|
+
if (root.state.status !== "open" || root.ready.status === "rejected") return;
|
|
15376
|
+
if (root.ready.status === "pending") {
|
|
15377
|
+
root.ready.then(commit, logRecoverableError);
|
|
15378
|
+
return;
|
|
15379
|
+
}
|
|
15380
|
+
const onCreated = root.configuration.previous?.onCreated;
|
|
15381
|
+
const element = /* @__PURE__ */ jsxRuntime.jsx(Provider, { store, children, onCreated, rootElement: canvas });
|
|
15382
|
+
if (mounted) {
|
|
15383
|
+
reconciler.updateContainer(element, fiber, null, noop);
|
|
15384
|
+
return;
|
|
15385
|
+
}
|
|
15386
|
+
mounted = true;
|
|
15387
|
+
reconciler.updateContainerSync(element, fiber, null, noop);
|
|
15388
|
+
reconciler.flushSyncWork();
|
|
15389
|
+
};
|
|
15390
|
+
commit();
|
|
15391
|
+
return store;
|
|
15392
|
+
},
|
|
15393
|
+
unmount() {
|
|
15394
|
+
if (_roots.get(canvas) === root) unmountComponentAtNode(canvas);
|
|
15395
|
+
}
|
|
15396
|
+
};
|
|
15397
|
+
}
|
|
15398
|
+
function Provider({
|
|
15399
|
+
store,
|
|
15400
|
+
children,
|
|
15401
|
+
onCreated,
|
|
15402
|
+
rootElement
|
|
15403
|
+
}) {
|
|
15404
|
+
textureStaging.useIsomorphicLayoutEffect(() => {
|
|
15405
|
+
const state = store.getState();
|
|
15406
|
+
state.set((state2) => ({ internal: { ...state2.internal, active: true } }));
|
|
15407
|
+
if (onCreated) onCreated(state);
|
|
15408
|
+
if (!store.getState().events.connected) state.events.connect?.(rootElement);
|
|
15409
|
+
}, []);
|
|
15410
|
+
return /* @__PURE__ */ jsxRuntime.jsx(textureStaging.context.Provider, { value: store, children });
|
|
15411
|
+
}
|
|
15412
|
+
function unmountComponentAtNode(canvas, callback) {
|
|
15413
|
+
const claim = Symbol("unmount");
|
|
15414
|
+
const root = _roots.get(canvas);
|
|
15415
|
+
if (!root || !transitionRoot(root, { type: "unmount", token: claim })) return;
|
|
15416
|
+
root.store.getState().internal.active = false;
|
|
15417
|
+
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
15418
|
+
if (root.state.status !== "closing" || root.state.token !== claim) return;
|
|
15419
|
+
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
15420
|
+
if (root.state.status !== "closing" || root.state.token !== claim) return;
|
|
15421
|
+
if (root.ready.status === "pending") root.ready.then(teardown, teardown);
|
|
15422
|
+
else teardown();
|
|
15423
|
+
});
|
|
15424
|
+
});
|
|
15425
|
+
function teardown() {
|
|
15426
|
+
if (root.ready.status === "pending") {
|
|
15427
|
+
root.ready.then(teardown, teardown);
|
|
15428
|
+
return;
|
|
15429
|
+
}
|
|
15430
|
+
if (!transitionRoot(root, { type: "dispose", token: claim })) return;
|
|
15431
|
+
_roots.delete(canvas);
|
|
15432
|
+
const state = root.store.getState();
|
|
15433
|
+
const internal = state.internal;
|
|
15434
|
+
internal.active = false;
|
|
15435
|
+
const attempt = (step) => {
|
|
15436
|
+
try {
|
|
15437
|
+
return step();
|
|
15438
|
+
} catch (error) {
|
|
15439
|
+
console.warn("[R3F] Error while unmounting root; teardown may be incomplete:", error);
|
|
15440
|
+
}
|
|
15441
|
+
};
|
|
15442
|
+
attempt(() => internal.unwatchDpr?.());
|
|
15443
|
+
internal.unwatchDpr = void 0;
|
|
15444
|
+
attempt(() => internal.unregisterRoot?.());
|
|
15445
|
+
internal.unregisterRoot = void 0;
|
|
15446
|
+
attempt(() => textureStaging.detachRootExtensions(root.store));
|
|
15447
|
+
attempt(() => internal.unregisterPrimary?.());
|
|
15448
|
+
attempt(() => internal.untrackStandalone?.());
|
|
15449
|
+
attempt(() => state.events.disconnect?.());
|
|
15450
|
+
if (!internal.isSecondary && internal.actualRenderer?.xr && state.xr) attempt(() => state.xr.disconnect());
|
|
15451
|
+
attempt(() => cleanupHelperGroup(root.store));
|
|
15452
|
+
if (state.scene) attempt(() => dispose(state.scene));
|
|
15453
|
+
const canvasTarget = internal.canvasTarget;
|
|
15454
|
+
if (internal.isSecondary && canvasTarget?.dispose) attempt(() => canvasTarget.dispose());
|
|
15455
|
+
const released = attempt(() => internal.releaseRenderer?.());
|
|
15456
|
+
internal.releaseRenderer = void 0;
|
|
15457
|
+
if (callback) {
|
|
15458
|
+
if (released) {
|
|
15459
|
+
released.then(() => callback(canvas)).catch((error) => console.warn("[R3F] Error in unmount callback", error));
|
|
15460
|
+
} else {
|
|
15461
|
+
callback(canvas);
|
|
15462
|
+
}
|
|
15463
|
+
}
|
|
15464
|
+
}
|
|
15465
|
+
}
|
|
15466
|
+
|
|
15467
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
15468
|
+
const isConstructor = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
15469
|
+
function getLoader(Proto) {
|
|
15470
|
+
if (isConstructor(Proto)) {
|
|
15471
|
+
let loader = memoizedLoaders.get(Proto);
|
|
15472
|
+
if (!loader) {
|
|
15473
|
+
loader = new Proto();
|
|
15474
|
+
memoizedLoaders.set(Proto, loader);
|
|
15475
|
+
}
|
|
15476
|
+
return loader;
|
|
15477
|
+
}
|
|
15478
|
+
return Proto;
|
|
15479
|
+
}
|
|
15480
|
+
function loadingFn(extensions, onProgress) {
|
|
15481
|
+
return function(Proto, input) {
|
|
15482
|
+
const loader = getLoader(Proto);
|
|
15483
|
+
if (extensions) extensions(loader);
|
|
15484
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
15485
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
15486
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
15487
|
+
return data;
|
|
15488
|
+
});
|
|
15489
|
+
}
|
|
15490
|
+
return new Promise(
|
|
15491
|
+
(res, reject) => loader.load(
|
|
15492
|
+
input,
|
|
15493
|
+
(data) => {
|
|
15494
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
15495
|
+
res(data);
|
|
15496
|
+
},
|
|
15497
|
+
onProgress,
|
|
15498
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
15499
|
+
)
|
|
15500
|
+
);
|
|
15501
|
+
};
|
|
15502
|
+
}
|
|
15503
|
+
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
15504
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
15505
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
15506
|
+
const fn = loadingFn(extensions, onProgress);
|
|
15507
|
+
const results = cacheKeys.map(
|
|
15508
|
+
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
15509
|
+
);
|
|
15510
|
+
const stableRef = React.useRef(null);
|
|
15511
|
+
const previous = stableRef.current;
|
|
15512
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
15513
|
+
stableRef.current = stable;
|
|
15514
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
15515
|
+
}
|
|
15516
|
+
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
15517
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
15518
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
15519
|
+
cacheKeys.forEach(
|
|
15520
|
+
(key, index) => suspendReact.preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
15521
|
+
);
|
|
15522
|
+
};
|
|
15523
|
+
useLoader.clear = function(loader, input, cacheKey) {
|
|
15524
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
15525
|
+
cacheKeys.forEach((key) => suspendReact.clear([loader, key]));
|
|
15526
|
+
};
|
|
15527
|
+
useLoader.loader = getLoader;
|
|
15528
|
+
|
|
15529
|
+
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
15530
|
+
function getUrls(input) {
|
|
15531
|
+
if (typeof input === "string") return [input];
|
|
15532
|
+
if (Array.isArray(input)) return input;
|
|
15533
|
+
return Object.values(input);
|
|
15534
|
+
}
|
|
15535
|
+
function inputSignature(input) {
|
|
15536
|
+
if (typeof input === "string") return input;
|
|
15537
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
15538
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
15539
|
+
}
|
|
15540
|
+
function allUrlsCached(urls, textureCache) {
|
|
15541
|
+
return urls.every((url) => textureCache.has(url));
|
|
15542
|
+
}
|
|
15543
|
+
function buildFromCache(input, textureCache) {
|
|
15544
|
+
if (typeof input === "string") {
|
|
15545
|
+
return textureCache.get(input);
|
|
15546
|
+
} else if (Array.isArray(input)) {
|
|
15547
|
+
return input.map((url) => textureCache.get(url));
|
|
15548
|
+
} else {
|
|
15549
|
+
const result = {};
|
|
15550
|
+
const objInput = input;
|
|
15551
|
+
for (const key in objInput) {
|
|
15552
|
+
result[key] = textureCache.get(objInput[key]);
|
|
15553
|
+
}
|
|
15554
|
+
return result;
|
|
15555
|
+
}
|
|
15556
|
+
}
|
|
15557
|
+
function useTexture(input, optionsOrOnLoad) {
|
|
15558
|
+
const renderer = textureStaging.useThree((state) => state.internal.actualRenderer);
|
|
15559
|
+
const store = textureStaging.useStore();
|
|
15560
|
+
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
15561
|
+
const { onLoad, cache = true } = options;
|
|
15562
|
+
const onLoadRef = React.useRef(onLoad);
|
|
15563
|
+
onLoadRef.current = onLoad;
|
|
15564
|
+
const onLoadCalledForRef = React.useRef(null);
|
|
15565
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
15566
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
15567
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
15568
|
+
const cachedResult = React.useMemo(() => {
|
|
15569
|
+
if (!cache) return null;
|
|
15570
|
+
const textures = store.getState().textures;
|
|
15571
|
+
if (!allUrlsCached(urls, textures)) return null;
|
|
15572
|
+
return buildFromCache(stableInput, textures);
|
|
15573
|
+
}, [cache, urls, stableInput, store]);
|
|
15574
|
+
const loadedTextures = useLoader(
|
|
15575
|
+
getThree().TextureLoader,
|
|
15576
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
15577
|
+
);
|
|
15578
|
+
const mappedTextures = React.useMemo(() => {
|
|
15579
|
+
if (cachedResult) return cachedResult;
|
|
15580
|
+
if (IsObject(stableInput)) {
|
|
15581
|
+
const keyed = {};
|
|
15582
|
+
const textureArray = loadedTextures;
|
|
15583
|
+
let i = 0;
|
|
15584
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
15585
|
+
return keyed;
|
|
15586
|
+
} else {
|
|
15587
|
+
return loadedTextures;
|
|
15588
|
+
}
|
|
15589
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
15590
|
+
React.useLayoutEffect(() => {
|
|
15591
|
+
if (cachedResult) return;
|
|
15592
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
15593
|
+
onLoadCalledForRef.current = inputKey;
|
|
15594
|
+
onLoadRef.current?.(mappedTextures);
|
|
15595
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
15596
|
+
React.useEffect(() => {
|
|
15597
|
+
if (cachedResult) return;
|
|
15598
|
+
if ("initTexture" in renderer) {
|
|
15599
|
+
let textureArray = [];
|
|
15600
|
+
if (Array.isArray(loadedTextures)) {
|
|
15601
|
+
textureArray = loadedTextures;
|
|
15602
|
+
} else if (loadedTextures.isTexture) {
|
|
15603
|
+
textureArray = [loadedTextures];
|
|
15604
|
+
} else if (IsObject(loadedTextures)) {
|
|
15605
|
+
textureArray = Object.values(loadedTextures);
|
|
14934
15606
|
}
|
|
14935
|
-
|
|
14936
|
-
if (
|
|
14937
|
-
|
|
14938
|
-
const support = wantsGL ? await webgl() : await webgpu();
|
|
14939
|
-
registerThree(support.three);
|
|
14940
|
-
state.internal.support = support;
|
|
14941
|
-
ensureStoreThreeObjects(store);
|
|
14942
|
-
if (support.kind === "webgl") {
|
|
14943
|
-
renderer = await resolveRenderer(glConfig, defaultGLProps, support.Renderer);
|
|
14944
|
-
state.internal.actualRenderer = renderer;
|
|
14945
|
-
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
14946
|
-
} else if (primaryCanvas) {
|
|
14947
|
-
const primary = await waitForPrimary(primaryCanvas);
|
|
14948
|
-
renderer = primary.renderer;
|
|
14949
|
-
state.internal.actualRenderer = renderer;
|
|
14950
|
-
const canvasTarget = new support.CanvasTarget(canvas);
|
|
14951
|
-
primary.store.setState((prev) => ({
|
|
14952
|
-
internal: { ...prev.internal, isMultiCanvas: true }
|
|
14953
|
-
}));
|
|
14954
|
-
state.set((prev) => ({
|
|
14955
|
-
webGPUSupported: primary.store.getState().webGPUSupported,
|
|
14956
|
-
renderer,
|
|
14957
|
-
primaryStore: primary.store,
|
|
14958
|
-
internal: {
|
|
14959
|
-
...prev.internal,
|
|
14960
|
-
canvasTarget,
|
|
14961
|
-
isMultiCanvas: true,
|
|
14962
|
-
isSecondary: true,
|
|
14963
|
-
targetId: primaryCanvas
|
|
14964
|
-
}
|
|
14965
|
-
}));
|
|
14966
|
-
} else {
|
|
14967
|
-
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, support.Renderer);
|
|
14968
|
-
if (!renderer.hasInitialized?.()) {
|
|
14969
|
-
const size2 = computeInitialSize(canvas, propsSize);
|
|
14970
|
-
if (size2.width > 0 && size2.height > 0) {
|
|
14971
|
-
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14972
|
-
renderer.setSize(size2.width, size2.height, false);
|
|
14973
|
-
}
|
|
14974
|
-
await renderer.init();
|
|
14975
|
-
}
|
|
14976
|
-
const backend = renderer.backend;
|
|
14977
|
-
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
14978
|
-
state.internal.actualRenderer = renderer;
|
|
14979
|
-
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14980
|
-
if (canvasId && !state.internal.isSecondary) {
|
|
14981
|
-
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14982
|
-
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14983
|
-
state.set((prev) => ({
|
|
14984
|
-
internal: {
|
|
14985
|
-
...prev.internal,
|
|
14986
|
-
canvasTarget,
|
|
14987
|
-
unregisterPrimary
|
|
14988
|
-
}
|
|
14989
|
-
}));
|
|
14990
|
-
}
|
|
14991
|
-
}
|
|
14992
|
-
})().catch((err) => {
|
|
14993
|
-
rendererSetup = null;
|
|
14994
|
-
throw err;
|
|
14995
|
-
});
|
|
15607
|
+
textureArray.forEach((texture) => {
|
|
15608
|
+
if (texture?.isTexture) {
|
|
15609
|
+
renderer.initTexture(texture);
|
|
14996
15610
|
}
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
|
|
15000
|
-
|
|
15001
|
-
|
|
15002
|
-
|
|
15003
|
-
|
|
15004
|
-
const
|
|
15005
|
-
|
|
15006
|
-
|
|
15007
|
-
|
|
15008
|
-
|
|
15009
|
-
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
const isCamera = cameraOptions?.isCamera;
|
|
15013
|
-
const camera = isCamera ? cameraOptions : orthographic ? new three.OrthographicCamera(0, 0, 0, 0, 0.1, 1e3) : new three.PerspectiveCamera(50, 0, 0.1, 1e3);
|
|
15014
|
-
if (!isCamera) {
|
|
15015
|
-
camera.position.z = 5;
|
|
15016
|
-
if (cameraOptions) {
|
|
15017
|
-
applyProps(camera, cameraOptions);
|
|
15018
|
-
if (!camera.manual) {
|
|
15019
|
-
const projectionProps = ["aspect", "left", "right", "bottom", "top"];
|
|
15020
|
-
if (projectionProps.some((prop) => prop in cameraOptions)) {
|
|
15021
|
-
camera.manual = true;
|
|
15022
|
-
camera.updateProjectionMatrix();
|
|
15023
|
-
}
|
|
15024
|
-
}
|
|
15611
|
+
});
|
|
15612
|
+
}
|
|
15613
|
+
}, [renderer, loadedTextures, cachedResult]);
|
|
15614
|
+
React.useEffect(() => {
|
|
15615
|
+
if (!cache) return;
|
|
15616
|
+
const urlTextureMap = urlTextureEntries(stableInput, mappedTextures);
|
|
15617
|
+
store.setState((state) => {
|
|
15618
|
+
const refs = new Map(state._textureRefs);
|
|
15619
|
+
let textures = state.textures;
|
|
15620
|
+
let added = false;
|
|
15621
|
+
for (const [url, texture] of urlTextureMap) {
|
|
15622
|
+
if (!textures.has(url)) {
|
|
15623
|
+
if (!added) {
|
|
15624
|
+
textures = new Map(textures);
|
|
15625
|
+
added = true;
|
|
15025
15626
|
}
|
|
15026
|
-
|
|
15627
|
+
textures.set(url, texture);
|
|
15027
15628
|
}
|
|
15028
|
-
|
|
15029
|
-
tempCamera = camera;
|
|
15030
|
-
raycaster.camera = camera;
|
|
15031
|
-
}
|
|
15032
|
-
if (!state.scene) {
|
|
15033
|
-
let scene;
|
|
15034
|
-
if (sceneOptions?.isScene) {
|
|
15035
|
-
scene = sceneOptions;
|
|
15036
|
-
prepare(scene, store, "", {});
|
|
15037
|
-
} else {
|
|
15038
|
-
scene = new three.Scene();
|
|
15039
|
-
prepare(scene, store, "", {});
|
|
15040
|
-
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
15041
|
-
}
|
|
15042
|
-
state.set((prev) => ({
|
|
15043
|
-
scene,
|
|
15044
|
-
rootScene: scene,
|
|
15045
|
-
internal: { ...prev.internal, container: scene }
|
|
15046
|
-
}));
|
|
15047
|
-
const camera = tempCamera;
|
|
15048
|
-
if (camera && !camera.parent) scene.add(camera);
|
|
15049
|
-
}
|
|
15050
|
-
if (events && !state.events.handlers) {
|
|
15051
|
-
state.set({ events: events(store) });
|
|
15052
|
-
let wasEnabled = true;
|
|
15053
|
-
store.subscribe((state2) => {
|
|
15054
|
-
const { enabled } = state2.events;
|
|
15055
|
-
if (enabled && !wasEnabled) {
|
|
15056
|
-
state2.events.update?.();
|
|
15057
|
-
}
|
|
15058
|
-
wasEnabled = enabled;
|
|
15059
|
-
});
|
|
15060
|
-
}
|
|
15061
|
-
if (_sizeProps !== void 0) {
|
|
15062
|
-
state.set({ _sizeProps });
|
|
15629
|
+
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
15063
15630
|
}
|
|
15064
|
-
|
|
15065
|
-
|
|
15631
|
+
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
15632
|
+
});
|
|
15633
|
+
textureStaging.unstageTextures(
|
|
15634
|
+
store,
|
|
15635
|
+
urlTextureMap.map(([url]) => url)
|
|
15636
|
+
);
|
|
15637
|
+
return () => store.setState((state) => {
|
|
15638
|
+
const refs = new Map(state._textureRefs);
|
|
15639
|
+
for (const [url] of urlTextureMap) {
|
|
15640
|
+
const next = (refs.get(url) ?? 0) - 1;
|
|
15641
|
+
if (next <= 0) refs.delete(url);
|
|
15642
|
+
else refs.set(url, next);
|
|
15066
15643
|
}
|
|
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
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
state.set({ xr });
|
|
15122
|
-
}
|
|
15123
|
-
if (renderer.shadowMap && !is.equ(shadows, lastConfiguredProps.shadows, shallowLoose)) {
|
|
15124
|
-
lastConfiguredProps.shadows = shadows;
|
|
15125
|
-
const oldEnabled = renderer.shadowMap.enabled;
|
|
15126
|
-
const oldType = renderer.shadowMap.type;
|
|
15127
|
-
renderer.shadowMap.enabled = !!shadows;
|
|
15128
|
-
if (is.boo(shadows)) {
|
|
15129
|
-
renderer.shadowMap.type = three.PCFShadowMap;
|
|
15130
|
-
} else if (is.str(shadows)) {
|
|
15131
|
-
if (shadows === "soft") {
|
|
15132
|
-
extensions.notifyDepreciated({
|
|
15133
|
-
heading: 'shadows="soft" is deprecated',
|
|
15134
|
-
body: "Three has depreciated soft and improved basic PCFShadows, we converted for you.",
|
|
15135
|
-
link: "https://github.com/mrdoob/three.js/wiki/Migration-Guide?utm_source=chatgpt.com#181--182"
|
|
15136
|
-
});
|
|
15644
|
+
return { _textureRefs: refs };
|
|
15645
|
+
});
|
|
15646
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
15647
|
+
if (cache && !cachedResult) textureStaging.stageTextures(store, urlTextureEntries(stableInput, mappedTextures));
|
|
15648
|
+
return mappedTextures;
|
|
15649
|
+
}
|
|
15650
|
+
function urlTextureEntries(input, textures) {
|
|
15651
|
+
if (typeof input === "string") return [[input, textures]];
|
|
15652
|
+
if (Array.isArray(input)) return input.map((url, i) => [url, textures[i]]);
|
|
15653
|
+
const record = textures;
|
|
15654
|
+
return Object.keys(input).map((key) => [input[key], record[key]]);
|
|
15655
|
+
}
|
|
15656
|
+
useTexture.preload = (url) => {
|
|
15657
|
+
whenThree().then((three) => useLoader.preload(three.TextureLoader, url));
|
|
15658
|
+
};
|
|
15659
|
+
useTexture.clear = (input) => {
|
|
15660
|
+
if (hasThree()) useLoader.clear(getThree().TextureLoader, input);
|
|
15661
|
+
};
|
|
15662
|
+
const Texture = ({
|
|
15663
|
+
children,
|
|
15664
|
+
input,
|
|
15665
|
+
onLoad,
|
|
15666
|
+
cache
|
|
15667
|
+
}) => {
|
|
15668
|
+
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
15669
|
+
const ret = useTexture(input, options);
|
|
15670
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children?.(ret) });
|
|
15671
|
+
};
|
|
15672
|
+
|
|
15673
|
+
function useTextures(selector) {
|
|
15674
|
+
const store = textureStaging.useStore();
|
|
15675
|
+
const registry = React.useMemo(() => {
|
|
15676
|
+
const getState = store.getState;
|
|
15677
|
+
const setState = store.setState;
|
|
15678
|
+
const getOne = (key) => getState().textures.get(key);
|
|
15679
|
+
return {
|
|
15680
|
+
get all() {
|
|
15681
|
+
return getState().textures;
|
|
15682
|
+
},
|
|
15683
|
+
get(input) {
|
|
15684
|
+
if (typeof input === "string") return getOne(input);
|
|
15685
|
+
if (Array.isArray(input)) return input.map(getOne);
|
|
15686
|
+
const out = {};
|
|
15687
|
+
for (const name in input) out[name] = getOne(input[name]);
|
|
15688
|
+
return out;
|
|
15689
|
+
},
|
|
15690
|
+
has: (key) => getState().textures.has(key),
|
|
15691
|
+
add(keyOrRecord, texture) {
|
|
15692
|
+
setState((state) => {
|
|
15693
|
+
const textures = new Map(state.textures);
|
|
15694
|
+
if (typeof keyOrRecord === "string") {
|
|
15695
|
+
textures.set(keyOrRecord, texture);
|
|
15696
|
+
} else {
|
|
15697
|
+
for (const key in keyOrRecord) textures.set(key, keyOrRecord[key]);
|
|
15137
15698
|
}
|
|
15138
|
-
|
|
15139
|
-
basic: three.BasicShadowMap,
|
|
15140
|
-
percentage: three.PCFShadowMap,
|
|
15141
|
-
soft: three.PCFShadowMap,
|
|
15142
|
-
variance: three.VSMShadowMap
|
|
15143
|
-
};
|
|
15144
|
-
renderer.shadowMap.type = types[shadows] ?? three.PCFShadowMap;
|
|
15145
|
-
} else if (is.obj(shadows)) {
|
|
15146
|
-
Object.assign(renderer.shadowMap, shadows);
|
|
15147
|
-
}
|
|
15148
|
-
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
15149
|
-
renderer.shadowMap.needsUpdate = true;
|
|
15150
|
-
}
|
|
15151
|
-
}
|
|
15152
|
-
if (!configured) {
|
|
15153
|
-
renderer.outputColorSpace = three.SRGBColorSpace;
|
|
15154
|
-
renderer.toneMapping = three.ACESFilmicToneMapping;
|
|
15155
|
-
}
|
|
15156
|
-
const textureColorSpace = requestedTextureColorSpace ?? three.SRGBColorSpace;
|
|
15157
|
-
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
15158
|
-
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
15159
|
-
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
15160
|
-
}
|
|
15161
|
-
const r3fProps = ["textureColorSpace"];
|
|
15162
|
-
const constructorOnlyProps = ["samples", "antialias", "alpha", "canvas", "powerPreference"];
|
|
15163
|
-
const nonApplyProps = [...r3fProps, ...constructorOnlyProps];
|
|
15164
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
15165
|
-
const glProps = {};
|
|
15166
|
-
for (const key in glConfig) {
|
|
15167
|
-
if (!nonApplyProps.includes(key)) glProps[key] = glConfig[key];
|
|
15168
|
-
}
|
|
15169
|
-
applyProps(renderer, glProps);
|
|
15170
|
-
}
|
|
15171
|
-
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
15172
|
-
const currentRenderer = state.renderer;
|
|
15173
|
-
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
15174
|
-
const rendererProps = {};
|
|
15175
|
-
for (const key in rendererConfig) {
|
|
15176
|
-
if (!nonApplyProps.includes(key)) rendererProps[key] = rendererConfig[key];
|
|
15177
|
-
}
|
|
15178
|
-
applyProps(currentRenderer, rendererProps);
|
|
15179
|
-
}
|
|
15180
|
-
}
|
|
15181
|
-
const scheduler$1 = scheduler.getScheduler();
|
|
15182
|
-
const rootId = state.internal.rootId;
|
|
15183
|
-
if (!rootId) {
|
|
15184
|
-
const newRootId = canvasId || scheduler$1.generateRootId();
|
|
15185
|
-
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
15186
|
-
getState: () => store.getState(),
|
|
15187
|
-
onError: (err) => store.getState().setError(err),
|
|
15188
|
-
frameloop: store.getState().frameloop,
|
|
15189
|
-
before: schedulerConfig?.before,
|
|
15190
|
-
after: schedulerConfig?.after,
|
|
15191
|
-
order: schedulerConfig?.order
|
|
15699
|
+
return { textures };
|
|
15192
15700
|
});
|
|
15193
|
-
|
|
15194
|
-
|
|
15195
|
-
|
|
15196
|
-
|
|
15197
|
-
|
|
15198
|
-
|
|
15199
|
-
|
|
15200
|
-
|
|
15201
|
-
|
|
15202
|
-
renderer2.backend?.updateSize?.();
|
|
15203
|
-
}
|
|
15204
|
-
}
|
|
15205
|
-
},
|
|
15206
|
-
{
|
|
15207
|
-
id: `${newRootId}_canvasTarget`,
|
|
15208
|
-
rootId: newRootId,
|
|
15209
|
-
phase: "start",
|
|
15210
|
-
system: true
|
|
15211
|
-
}
|
|
15212
|
-
);
|
|
15213
|
-
const unregisterEventsFlush = scheduler$1.register(
|
|
15214
|
-
() => {
|
|
15215
|
-
const state2 = store.getState();
|
|
15216
|
-
state2.events.flush?.();
|
|
15217
|
-
},
|
|
15218
|
-
{
|
|
15219
|
-
id: `${newRootId}_events`,
|
|
15220
|
-
rootId: newRootId,
|
|
15221
|
-
phase: "input",
|
|
15222
|
-
system: true
|
|
15223
|
-
}
|
|
15224
|
-
);
|
|
15225
|
-
const unregisterFrustum = scheduler$1.register(
|
|
15226
|
-
() => {
|
|
15227
|
-
const state2 = store.getState();
|
|
15228
|
-
if (state2.autoUpdateFrustum && state2.camera) {
|
|
15229
|
-
updateFrustum(state2.camera, state2.frustum);
|
|
15230
|
-
}
|
|
15231
|
-
},
|
|
15232
|
-
{
|
|
15233
|
-
id: `${newRootId}_frustum`,
|
|
15234
|
-
rootId: newRootId,
|
|
15235
|
-
before: "render",
|
|
15236
|
-
system: true
|
|
15237
|
-
}
|
|
15238
|
-
);
|
|
15239
|
-
const unregisterVisibility = scheduler$1.register(
|
|
15240
|
-
() => {
|
|
15241
|
-
const state2 = store.getState();
|
|
15242
|
-
checkVisibility(state2);
|
|
15243
|
-
},
|
|
15244
|
-
{
|
|
15245
|
-
id: `${newRootId}_visibility`,
|
|
15246
|
-
rootId: newRootId,
|
|
15247
|
-
before: "render",
|
|
15248
|
-
system: true,
|
|
15249
|
-
after: `${newRootId}_frustum`
|
|
15250
|
-
}
|
|
15251
|
-
);
|
|
15252
|
-
const unregisterRender = scheduler$1.register(
|
|
15253
|
-
() => {
|
|
15254
|
-
const state2 = store.getState();
|
|
15255
|
-
const renderer2 = state2.internal.actualRenderer;
|
|
15256
|
-
const userHandlesRender = scheduler$1.hasUserJobsInPhase("render", newRootId);
|
|
15257
|
-
if (userHandlesRender || state2.internal.priority) return;
|
|
15258
|
-
try {
|
|
15259
|
-
const renderOverride = state2.internal.renderOverride;
|
|
15260
|
-
if (renderOverride) renderOverride();
|
|
15261
|
-
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
15262
|
-
} catch (error) {
|
|
15263
|
-
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
15264
|
-
}
|
|
15265
|
-
},
|
|
15266
|
-
{
|
|
15267
|
-
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
15268
|
-
id: canvasId || `${newRootId}_render`,
|
|
15269
|
-
rootId: newRootId,
|
|
15270
|
-
phase: "render",
|
|
15271
|
-
system: true,
|
|
15272
|
-
// Internal flag: this is a system job, not user-controlled
|
|
15273
|
-
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
15274
|
-
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
15275
|
-
}
|
|
15276
|
-
);
|
|
15277
|
-
state.set((state2) => ({
|
|
15278
|
-
internal: {
|
|
15279
|
-
...state2.internal,
|
|
15280
|
-
rootId: newRootId,
|
|
15281
|
-
unregisterRoot: () => {
|
|
15282
|
-
unregisterRoot();
|
|
15283
|
-
unregisterCanvasTarget();
|
|
15284
|
-
unregisterEventsFlush();
|
|
15285
|
-
unregisterFrustum();
|
|
15286
|
-
unregisterVisibility();
|
|
15287
|
-
unregisterRender();
|
|
15288
|
-
},
|
|
15289
|
-
scheduler: scheduler$1
|
|
15290
|
-
}
|
|
15291
|
-
}));
|
|
15292
|
-
} else {
|
|
15293
|
-
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
15294
|
-
if (constraintsChanged) {
|
|
15295
|
-
scheduler$1.setRootConstraints(rootId, {
|
|
15296
|
-
before: schedulerConfig?.before,
|
|
15297
|
-
after: schedulerConfig?.after
|
|
15298
|
-
});
|
|
15299
|
-
}
|
|
15300
|
-
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
15301
|
-
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
15701
|
+
},
|
|
15702
|
+
dispose(key, options) {
|
|
15703
|
+
const state = getState();
|
|
15704
|
+
const refs = state._textureRefs.get(key) ?? 0;
|
|
15705
|
+
if (refs > 0 && !options?.force) {
|
|
15706
|
+
console.warn(
|
|
15707
|
+
`[useTextures] "${key}" still has ${refs} active reference(s); skipping dispose. Pass { force: true } to override.`
|
|
15708
|
+
);
|
|
15709
|
+
return false;
|
|
15302
15710
|
}
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
});
|
|
15323
|
-
return store;
|
|
15324
|
-
},
|
|
15325
|
-
unmount() {
|
|
15326
|
-
unmountComponentAtNode(canvas);
|
|
15327
|
-
}
|
|
15328
|
-
};
|
|
15711
|
+
state.textures.get(key)?.dispose();
|
|
15712
|
+
setState((s) => {
|
|
15713
|
+
const textures = new Map(s.textures);
|
|
15714
|
+
textures.delete(key);
|
|
15715
|
+
const nextRefs = new Map(s._textureRefs);
|
|
15716
|
+
nextRefs.delete(key);
|
|
15717
|
+
return { textures, _textureRefs: nextRefs };
|
|
15718
|
+
});
|
|
15719
|
+
return true;
|
|
15720
|
+
},
|
|
15721
|
+
disposeAll() {
|
|
15722
|
+
for (const texture of getState().textures.values()) texture.dispose();
|
|
15723
|
+
setState({ textures: /* @__PURE__ */ new Map(), _textureRefs: /* @__PURE__ */ new Map() });
|
|
15724
|
+
}
|
|
15725
|
+
};
|
|
15726
|
+
}, [store]);
|
|
15727
|
+
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
15728
|
+
const selected = textureStaging.useThree(subscribe);
|
|
15729
|
+
return selector ? selected : registry;
|
|
15329
15730
|
}
|
|
15330
|
-
|
|
15331
|
-
|
|
15332
|
-
|
|
15333
|
-
|
|
15334
|
-
|
|
15335
|
-
|
|
15336
|
-
|
|
15337
|
-
|
|
15338
|
-
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15731
|
+
|
|
15732
|
+
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
15733
|
+
const support = textureStaging.useThree((s) => s.internal.support);
|
|
15734
|
+
const size = textureStaging.useThree((s) => s.size);
|
|
15735
|
+
let width;
|
|
15736
|
+
let height;
|
|
15737
|
+
let opts;
|
|
15738
|
+
if (typeof widthOrOptions === "object") {
|
|
15739
|
+
opts = widthOrOptions;
|
|
15740
|
+
} else if (typeof widthOrOptions === "number") {
|
|
15741
|
+
width = widthOrOptions;
|
|
15742
|
+
if (typeof heightOrOptions === "object") {
|
|
15743
|
+
height = widthOrOptions;
|
|
15744
|
+
opts = heightOrOptions;
|
|
15745
|
+
} else if (typeof heightOrOptions === "number") {
|
|
15746
|
+
height = heightOrOptions;
|
|
15747
|
+
opts = options;
|
|
15748
|
+
} else {
|
|
15749
|
+
height = widthOrOptions;
|
|
15750
|
+
}
|
|
15751
|
+
}
|
|
15752
|
+
return React.useMemo(() => {
|
|
15753
|
+
const w = width ?? size.width;
|
|
15754
|
+
const h = height ?? size.height;
|
|
15755
|
+
const Target = support.RenderTarget;
|
|
15756
|
+
return new Target(w, h, opts);
|
|
15757
|
+
}, [width, height, size.width, size.height, opts, support]);
|
|
15343
15758
|
}
|
|
15344
|
-
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
|
|
15348
|
-
|
|
15349
|
-
|
|
15350
|
-
|
|
15351
|
-
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
|
|
15759
|
+
|
|
15760
|
+
const presetsObj = {
|
|
15761
|
+
apartment: "lebombo_1k.hdr",
|
|
15762
|
+
city: "potsdamer_platz_1k.hdr",
|
|
15763
|
+
dawn: "kiara_1_dawn_1k.hdr",
|
|
15764
|
+
forest: "forest_slope_1k.hdr",
|
|
15765
|
+
lobby: "st_fagans_interior_1k.hdr",
|
|
15766
|
+
night: "dikhololo_night_1k.hdr",
|
|
15767
|
+
park: "rooitou_park_1k.hdr",
|
|
15768
|
+
studio: "studio_small_03_1k.hdr",
|
|
15769
|
+
sunset: "venice_sunset_1k.hdr",
|
|
15770
|
+
warehouse: "empty_warehouse_01_1k.hdr"
|
|
15771
|
+
};
|
|
15772
|
+
|
|
15773
|
+
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
15774
|
+
const isArray = (arr) => Array.isArray(arr);
|
|
15775
|
+
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
15776
|
+
const loadedLoaders = /* @__PURE__ */ new Map();
|
|
15777
|
+
const pendingLoaders = /* @__PURE__ */ new Map();
|
|
15778
|
+
function loadLoader(format) {
|
|
15779
|
+
let pending = pendingLoaders.get(format);
|
|
15780
|
+
if (!pending) {
|
|
15781
|
+
pending = importLoader(format).then(
|
|
15782
|
+
(loader) => {
|
|
15783
|
+
loadedLoaders.set(format, loader);
|
|
15784
|
+
return loader;
|
|
15785
|
+
},
|
|
15786
|
+
(error) => {
|
|
15787
|
+
pendingLoaders.delete(format);
|
|
15788
|
+
throw error;
|
|
15355
15789
|
}
|
|
15790
|
+
);
|
|
15791
|
+
pendingLoaders.set(format, pending);
|
|
15792
|
+
}
|
|
15793
|
+
return pending;
|
|
15794
|
+
}
|
|
15795
|
+
async function importLoader(format) {
|
|
15796
|
+
let loader;
|
|
15797
|
+
switch (format) {
|
|
15798
|
+
case "cube":
|
|
15799
|
+
loader = getThree().CubeTextureLoader;
|
|
15800
|
+
break;
|
|
15801
|
+
case "hdr-cube":
|
|
15802
|
+
loader = (await import('three/examples/jsm/loaders/HDRCubeTextureLoader.js')).HDRCubeTextureLoader;
|
|
15803
|
+
break;
|
|
15804
|
+
case "hdr":
|
|
15805
|
+
loader = (await import('three/examples/jsm/loaders/HDRLoader.js')).HDRLoader;
|
|
15806
|
+
break;
|
|
15807
|
+
case "exr":
|
|
15808
|
+
loader = (await import('three/examples/jsm/loaders/EXRLoader.js')).EXRLoader;
|
|
15809
|
+
break;
|
|
15810
|
+
case "jpg":
|
|
15811
|
+
loader = (await import('three/examples/jsm/loaders/UltraHDRLoader.js')).UltraHDRLoader;
|
|
15812
|
+
break;
|
|
15813
|
+
}
|
|
15814
|
+
return loader;
|
|
15815
|
+
}
|
|
15816
|
+
const LOADER_KEY = Symbol("r3f-environment-loader");
|
|
15817
|
+
function useEnvironmentLoader(format) {
|
|
15818
|
+
return suspendReact.suspend(() => loadLoader(format), [LOADER_KEY, format]);
|
|
15819
|
+
}
|
|
15820
|
+
function useEnvironment({
|
|
15821
|
+
files = defaultFiles,
|
|
15822
|
+
path = "",
|
|
15823
|
+
preset = void 0,
|
|
15824
|
+
colorSpace = void 0,
|
|
15825
|
+
extensions
|
|
15826
|
+
} = {}) {
|
|
15827
|
+
if (preset) {
|
|
15828
|
+
validatePreset(preset);
|
|
15829
|
+
files = presetsObj[preset];
|
|
15830
|
+
path = CUBEMAP_ROOT;
|
|
15831
|
+
}
|
|
15832
|
+
const multiFile = isArray(files);
|
|
15833
|
+
const { format, isCubemap } = getFormat(files);
|
|
15834
|
+
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
15835
|
+
const loader = useEnvironmentLoader(format);
|
|
15836
|
+
const loaderResult = useLoader(
|
|
15837
|
+
loader,
|
|
15838
|
+
multiFile ? [files] : files,
|
|
15839
|
+
(loader2) => {
|
|
15840
|
+
loader2.setPath?.(path);
|
|
15841
|
+
if (extensions) extensions(loader2);
|
|
15356
15842
|
}
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
|
|
15366
|
-
|
|
15367
|
-
|
|
15368
|
-
|
|
15369
|
-
|
|
15370
|
-
|
|
15371
|
-
|
|
15372
|
-
|
|
15373
|
-
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15843
|
+
);
|
|
15844
|
+
const texture = multiFile ? (
|
|
15845
|
+
// @ts-ignore
|
|
15846
|
+
loaderResult[0]
|
|
15847
|
+
) : loaderResult;
|
|
15848
|
+
const three = getThree();
|
|
15849
|
+
texture.mapping = isCubemap ? three.CubeReflectionMapping : three.EquirectangularReflectionMapping;
|
|
15850
|
+
texture.colorSpace = colorSpace ?? (isCubemap && format !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
15851
|
+
return texture;
|
|
15852
|
+
}
|
|
15853
|
+
const preloadDefaultOptions = {
|
|
15854
|
+
files: defaultFiles,
|
|
15855
|
+
path: "",
|
|
15856
|
+
preset: void 0,
|
|
15857
|
+
extensions: void 0
|
|
15858
|
+
};
|
|
15859
|
+
useEnvironment.preload = (preloadOptions) => {
|
|
15860
|
+
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
15861
|
+
let { files, path = "" } = options;
|
|
15862
|
+
const { preset, extensions } = options;
|
|
15863
|
+
if (preset) {
|
|
15864
|
+
validatePreset(preset);
|
|
15865
|
+
files = presetsObj[preset];
|
|
15866
|
+
path = CUBEMAP_ROOT;
|
|
15867
|
+
}
|
|
15868
|
+
const { format } = getFormat(files);
|
|
15869
|
+
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
15870
|
+
const input = isArray(files) ? [files] : files;
|
|
15871
|
+
loadLoader(format).then((loader) => {
|
|
15872
|
+
useLoader.preload(loader, input, (loader2) => {
|
|
15873
|
+
loader2.setPath?.(path);
|
|
15874
|
+
if (extensions) extensions(loader2);
|
|
15875
|
+
});
|
|
15876
|
+
});
|
|
15877
|
+
};
|
|
15878
|
+
const clearDefaultOptins = {
|
|
15879
|
+
files: defaultFiles,
|
|
15880
|
+
preset: void 0
|
|
15881
|
+
};
|
|
15882
|
+
useEnvironment.clear = (clearOptions) => {
|
|
15883
|
+
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
15884
|
+
let { files } = options;
|
|
15885
|
+
const { preset } = options;
|
|
15886
|
+
if (preset) {
|
|
15887
|
+
validatePreset(preset);
|
|
15888
|
+
files = presetsObj[preset];
|
|
15889
|
+
}
|
|
15890
|
+
const { format } = getFormat(files);
|
|
15891
|
+
if (!format) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
15892
|
+
const input = isArray(files) ? [files] : files;
|
|
15893
|
+
const clear = (loader2) => useLoader.clear(loader2, input);
|
|
15894
|
+
const loader = loadedLoaders.get(format);
|
|
15895
|
+
if (loader) {
|
|
15896
|
+
clear(loader);
|
|
15897
|
+
} else {
|
|
15898
|
+
const pending = pendingLoaders.get(format);
|
|
15899
|
+
if (pending) void pending.then(clear, () => {
|
|
15385
15900
|
});
|
|
15386
15901
|
}
|
|
15902
|
+
};
|
|
15903
|
+
function validatePreset(preset) {
|
|
15904
|
+
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
15905
|
+
}
|
|
15906
|
+
function getFormat(files) {
|
|
15907
|
+
const isCubemap = isArray(files) && files.length === 6;
|
|
15908
|
+
const firstEntry = isArray(files) ? files[0] : files;
|
|
15909
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
15910
|
+
let format;
|
|
15911
|
+
if (isCubemap) format = firstExtension === "hdr" ? "hdr-cube" : "cube";
|
|
15912
|
+
else if (firstEntry.startsWith("data:application/exr")) format = "exr";
|
|
15913
|
+
else if (firstEntry.startsWith("data:application/hdr")) format = "hdr";
|
|
15914
|
+
else if (firstEntry.startsWith("data:image/jpeg")) format = "jpg";
|
|
15915
|
+
else if (firstExtension === "hdr" || firstExtension === "exr") format = firstExtension;
|
|
15916
|
+
else if (firstExtension === "jpg" || firstExtension === "jpeg") format = "jpg";
|
|
15917
|
+
return { format, isCubemap };
|
|
15918
|
+
}
|
|
15919
|
+
|
|
15920
|
+
function useInstanceHandle(ref) {
|
|
15921
|
+
const instance = React.useRef(null);
|
|
15922
|
+
React.useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
15923
|
+
return instance;
|
|
15924
|
+
}
|
|
15925
|
+
function useGraph(object) {
|
|
15926
|
+
return React.useMemo(() => buildGraph(object), [object]);
|
|
15387
15927
|
}
|
|
15928
|
+
|
|
15388
15929
|
function createPortal(children, container, state) {
|
|
15389
15930
|
return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children, container, state });
|
|
15390
15931
|
}
|
|
@@ -15415,26 +15956,23 @@ function Portal({ children, container, state }) {
|
|
|
15415
15956
|
}
|
|
15416
15957
|
function PortalInner({ state = {}, children, container }) {
|
|
15417
15958
|
const { events, size, injectScene = true, ...rest } = state;
|
|
15418
|
-
const previousRoot =
|
|
15959
|
+
const previousRoot = textureStaging.useStore();
|
|
15419
15960
|
const [raycaster] = React.useState(() => new (getThree()).Raycaster());
|
|
15420
15961
|
const [pointer] = React.useState(() => new (getThree()).Vector2());
|
|
15421
15962
|
const [portalScene] = React.useState(() => {
|
|
15422
15963
|
if ("isScene" in container && container.isScene) return container;
|
|
15423
15964
|
if (!injectScene) return container;
|
|
15424
|
-
|
|
15425
|
-
container.add(scene);
|
|
15426
|
-
return scene;
|
|
15965
|
+
return new (getThree()).Scene();
|
|
15427
15966
|
});
|
|
15428
|
-
|
|
15967
|
+
textureStaging.useIsomorphicLayoutEffect(() => {
|
|
15968
|
+
if (portalScene === container || !injectScene) return;
|
|
15969
|
+
container.add(portalScene);
|
|
15429
15970
|
return () => {
|
|
15430
|
-
|
|
15431
|
-
container.remove(portalScene);
|
|
15432
|
-
dispose(portalScene);
|
|
15433
|
-
}
|
|
15971
|
+
container.remove(portalScene);
|
|
15434
15972
|
};
|
|
15435
15973
|
}, [portalScene, container, injectScene]);
|
|
15436
15974
|
const lastRootState = React.useRef(null);
|
|
15437
|
-
const inject =
|
|
15975
|
+
const inject = textureStaging.useMutableCallback((rootState, injectState) => {
|
|
15438
15976
|
const followed = {};
|
|
15439
15977
|
const lastRoot = lastRootState.current;
|
|
15440
15978
|
if (lastRoot) {
|
|
@@ -15485,7 +16023,7 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
15485
16023
|
onMutate(previousRoot.getState());
|
|
15486
16024
|
return store;
|
|
15487
16025
|
}, [previousRoot, container]);
|
|
15488
|
-
|
|
16026
|
+
textureStaging.useIsomorphicLayoutEffect(() => {
|
|
15489
16027
|
const onMutate = (prev) => usePortalStore.setState((state2) => inject.current(prev, state2));
|
|
15490
16028
|
const unsubscribe = previousRoot.subscribe(onMutate);
|
|
15491
16029
|
return unsubscribe;
|
|
@@ -15493,15 +16031,12 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
15493
16031
|
return (
|
|
15494
16032
|
// @ts-ignore, reconciler types are not maintained
|
|
15495
16033
|
/* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reconciler.createPortal(
|
|
15496
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16034
|
+
/* @__PURE__ */ jsxRuntime.jsx(textureStaging.context.Provider, { value: usePortalStore, children }),
|
|
15497
16035
|
usePortalStore,
|
|
15498
16036
|
null
|
|
15499
16037
|
) })
|
|
15500
16038
|
);
|
|
15501
16039
|
}
|
|
15502
|
-
function flushSync(fn) {
|
|
15503
|
-
return reconciler.flushSyncFromReconciler(fn);
|
|
15504
|
-
}
|
|
15505
16040
|
|
|
15506
16041
|
const isRef = (obj) => obj.current && obj.current.isScene;
|
|
15507
16042
|
const resolveScene = (scene) => isRef(scene) ? scene.current : scene;
|
|
@@ -15534,7 +16069,7 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
15534
16069
|
};
|
|
15535
16070
|
}
|
|
15536
16071
|
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
15537
|
-
const defaultScene =
|
|
16072
|
+
const defaultScene = textureStaging.useThree((state) => state.scene);
|
|
15538
16073
|
React__namespace.useLayoutEffect(() => {
|
|
15539
16074
|
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
15540
16075
|
});
|
|
@@ -15552,7 +16087,7 @@ function EnvironmentCube({
|
|
|
15552
16087
|
...rest
|
|
15553
16088
|
}) {
|
|
15554
16089
|
const texture = useEnvironment(rest);
|
|
15555
|
-
const defaultScene =
|
|
16090
|
+
const defaultScene = textureStaging.useThree((state) => state.scene);
|
|
15556
16091
|
React__namespace.useLayoutEffect(() => {
|
|
15557
16092
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
15558
16093
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -15587,11 +16122,11 @@ function EnvironmentPortal({
|
|
|
15587
16122
|
files,
|
|
15588
16123
|
path,
|
|
15589
16124
|
preset = void 0,
|
|
15590
|
-
extensions
|
|
16125
|
+
extensions
|
|
15591
16126
|
}) {
|
|
15592
|
-
const renderer =
|
|
15593
|
-
const support =
|
|
15594
|
-
const defaultScene =
|
|
16127
|
+
const renderer = textureStaging.useThree((state) => state.renderer);
|
|
16128
|
+
const support = textureStaging.useThree((state) => state.internal.support);
|
|
16129
|
+
const defaultScene = textureStaging.useThree((state) => state.scene);
|
|
15595
16130
|
const camera = React__namespace.useRef(null);
|
|
15596
16131
|
const [virtualScene] = React__namespace.useState(() => new (getThree()).Scene());
|
|
15597
16132
|
const fbo = React__namespace.useMemo(() => {
|
|
@@ -15635,7 +16170,7 @@ function EnvironmentPortal({
|
|
|
15635
16170
|
environmentRotation
|
|
15636
16171
|
]);
|
|
15637
16172
|
let count = 1;
|
|
15638
|
-
|
|
16173
|
+
textureStaging.useFrame(() => {
|
|
15639
16174
|
if (frames === Infinity || count < frames) {
|
|
15640
16175
|
const autoClear = renderer.autoClear;
|
|
15641
16176
|
renderer.autoClear = true;
|
|
@@ -15648,7 +16183,7 @@ function EnvironmentPortal({
|
|
|
15648
16183
|
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
15649
16184
|
children,
|
|
15650
16185
|
/* @__PURE__ */ jsxRuntime.jsx("cubeCamera", { ref: camera, args: [near, far, fbo] }),
|
|
15651
|
-
files || preset ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentCube, { background: true, files, preset, path, extensions
|
|
16186
|
+
files || preset ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentCube, { background: true, files, preset, path, extensions }) : map ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentMap, { background: true, map, extensions }) : null
|
|
15652
16187
|
] }),
|
|
15653
16188
|
virtualScene
|
|
15654
16189
|
) });
|
|
@@ -15678,7 +16213,7 @@ function EnvironmentGround(props) {
|
|
|
15678
16213
|
] });
|
|
15679
16214
|
}
|
|
15680
16215
|
function EnvironmentColor({ color, scene }) {
|
|
15681
|
-
const defaultScene =
|
|
16216
|
+
const defaultScene = textureStaging.useThree((state) => state.scene);
|
|
15682
16217
|
React__namespace.useLayoutEffect(() => {
|
|
15683
16218
|
if (color === void 0) return;
|
|
15684
16219
|
const target = resolveScene(scene || defaultScene);
|
|
@@ -15737,19 +16272,6 @@ function parseBackground(background) {
|
|
|
15737
16272
|
return null;
|
|
15738
16273
|
}
|
|
15739
16274
|
|
|
15740
|
-
function parseRendererConfig(rendererProp) {
|
|
15741
|
-
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
15742
|
-
if (isRendererConfig) {
|
|
15743
|
-
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
15744
|
-
return {
|
|
15745
|
-
primaryCanvas: pc,
|
|
15746
|
-
scheduler: sc,
|
|
15747
|
-
renderer: Object.keys(rest).length > 0 ? rest : rendererProp
|
|
15748
|
-
};
|
|
15749
|
-
}
|
|
15750
|
-
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
15751
|
-
}
|
|
15752
|
-
|
|
15753
16275
|
function CanvasImpl({
|
|
15754
16276
|
ref,
|
|
15755
16277
|
children,
|
|
@@ -15758,11 +16280,13 @@ function CanvasImpl({
|
|
|
15758
16280
|
style,
|
|
15759
16281
|
id,
|
|
15760
16282
|
gl,
|
|
15761
|
-
renderer
|
|
16283
|
+
renderer,
|
|
16284
|
+
primary,
|
|
16285
|
+
share,
|
|
16286
|
+
scheduler,
|
|
15762
16287
|
events = createPointerEvents,
|
|
15763
16288
|
eventSource,
|
|
15764
16289
|
eventPrefix,
|
|
15765
|
-
shadows,
|
|
15766
16290
|
orthographic,
|
|
15767
16291
|
frameloop,
|
|
15768
16292
|
dpr,
|
|
@@ -15784,8 +16308,12 @@ function CanvasImpl({
|
|
|
15784
16308
|
provider,
|
|
15785
16309
|
...props
|
|
15786
16310
|
}) {
|
|
15787
|
-
const {
|
|
15788
|
-
|
|
16311
|
+
const {
|
|
16312
|
+
shadows: removedShadows,
|
|
16313
|
+
primaryCanvas: removedPrimaryCanvas,
|
|
16314
|
+
...divProps
|
|
16315
|
+
} = props;
|
|
16316
|
+
const Bridge = textureStaging.useBridge();
|
|
15789
16317
|
const backgroundProps = React__namespace.useMemo(() => parseBackground(background), [background]);
|
|
15790
16318
|
const [hasInitialSize, setHasInitialSize] = React__namespace.useState(false);
|
|
15791
16319
|
const measureConfig = React__namespace.useMemo(() => {
|
|
@@ -15821,119 +16349,145 @@ function CanvasImpl({
|
|
|
15821
16349
|
const canvasRef = React__namespace.useRef(null);
|
|
15822
16350
|
const divRef = React__namespace.useRef(null);
|
|
15823
16351
|
React__namespace.useImperativeHandle(ref, () => canvasRef.current);
|
|
15824
|
-
const handlePointerMissed =
|
|
15825
|
-
const handleDragOverMissed =
|
|
15826
|
-
const handleDropMissed =
|
|
16352
|
+
const handlePointerMissed = textureStaging.useMutableCallback(onPointerMissed);
|
|
16353
|
+
const handleDragOverMissed = textureStaging.useMutableCallback(onDragOverMissed);
|
|
16354
|
+
const handleDropMissed = textureStaging.useMutableCallback(onDropMissed);
|
|
15827
16355
|
const [block, setBlock] = React__namespace.useState(false);
|
|
15828
16356
|
const [error, setError] = React__namespace.useState(false);
|
|
15829
16357
|
const [fallbackVisible, setFallbackVisible] = React__namespace.useState(false);
|
|
15830
16358
|
if (block) throw block;
|
|
15831
16359
|
if (error) throw error;
|
|
15832
16360
|
const root = React__namespace.useRef(null);
|
|
15833
|
-
const
|
|
15834
|
-
const
|
|
15835
|
-
|
|
15836
|
-
|
|
16361
|
+
const [gate, waitFor] = textureStaging.useGate();
|
|
16362
|
+
const rootState = React__namespace.useRef(null);
|
|
16363
|
+
const eventTarget = () => eventSource ? isRef$1(eventSource) ? eventSource.current : eventSource : divRef.current;
|
|
16364
|
+
const pointerMissed = React__namespace.useCallback(
|
|
16365
|
+
(...args) => handlePointerMissed.current?.(...args),
|
|
16366
|
+
[handlePointerMissed]
|
|
16367
|
+
);
|
|
16368
|
+
const dragOverMissed = React__namespace.useCallback(
|
|
16369
|
+
(...args) => handleDragOverMissed.current?.(...args),
|
|
16370
|
+
[handleDragOverMissed]
|
|
16371
|
+
);
|
|
16372
|
+
const dropMissed = React__namespace.useCallback(
|
|
16373
|
+
(...args) => handleDropMissed.current?.(...args),
|
|
16374
|
+
[handleDropMissed]
|
|
16375
|
+
);
|
|
16376
|
+
textureStaging.useIsomorphicLayoutEffect(() => {
|
|
15837
16377
|
if (fallbackVisible) return;
|
|
15838
16378
|
const canvas = canvasRef.current;
|
|
15839
16379
|
if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
|
|
15840
16380
|
if (!root.current) {
|
|
15841
16381
|
root.current = createRoot(canvas, provider);
|
|
15842
|
-
|
|
16382
|
+
textureStaging.notifyAlpha({
|
|
15843
16383
|
message: "React Three Fiber v10 is in ALPHA - expect breaking changes",
|
|
15844
16384
|
link: "https://github.com/pmndrs/react-three-fiber/discussions"
|
|
15845
16385
|
});
|
|
15846
|
-
const rootEntry = _roots.get(canvas);
|
|
15847
|
-
if (rootEntry?.store) {
|
|
15848
|
-
if (unsubscribeErrorRef.current) unsubscribeErrorRef.current();
|
|
15849
|
-
unsubscribeErrorRef.current = rootEntry.store.subscribe((state) => {
|
|
15850
|
-
if (state.error && effectActiveRef.current) {
|
|
15851
|
-
setError(state.error);
|
|
15852
|
-
}
|
|
15853
|
-
});
|
|
15854
|
-
}
|
|
15855
16386
|
}
|
|
15856
|
-
|
|
15857
|
-
|
|
15858
|
-
|
|
15859
|
-
|
|
15860
|
-
|
|
15861
|
-
|
|
15862
|
-
|
|
15863
|
-
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
|
|
15870
|
-
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
|
|
15875
|
-
|
|
15876
|
-
|
|
15877
|
-
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
|
|
15884
|
-
|
|
15885
|
-
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
|
|
15889
|
-
|
|
15890
|
-
|
|
15891
|
-
|
|
15892
|
-
|
|
15893
|
-
|
|
15894
|
-
|
|
15895
|
-
|
|
15896
|
-
}
|
|
15897
|
-
onCreated?.(state);
|
|
15898
|
-
}
|
|
15899
|
-
}).then(
|
|
15900
|
-
() => true,
|
|
15901
|
-
// Renderer setup failed (e.g. no WebGL/WebGPU support). The `fallback` prop lives
|
|
15902
|
-
// inside <canvas>, which browsers don't display, so surface it as visible DOM
|
|
15903
|
-
// instead; with no fallback, rethrow to an external error boundary. (#3757)
|
|
15904
|
-
(setupError) => {
|
|
15905
|
-
if (effectActiveRef.current) {
|
|
15906
|
-
if (fallback != null) setFallbackVisible(true);
|
|
15907
|
-
else setError(setupError);
|
|
15908
|
-
}
|
|
15909
|
-
return false;
|
|
16387
|
+
const current = root.current;
|
|
16388
|
+
current.configure({
|
|
16389
|
+
id,
|
|
16390
|
+
primary,
|
|
16391
|
+
share,
|
|
16392
|
+
scheduler,
|
|
16393
|
+
gl,
|
|
16394
|
+
renderer,
|
|
16395
|
+
scene,
|
|
16396
|
+
events,
|
|
16397
|
+
_primaryToken: primaryToken,
|
|
16398
|
+
...{ shadows: removedShadows, primaryCanvas: removedPrimaryCanvas },
|
|
16399
|
+
orthographic,
|
|
16400
|
+
frameloop,
|
|
16401
|
+
dpr,
|
|
16402
|
+
performance,
|
|
16403
|
+
raycaster,
|
|
16404
|
+
camera,
|
|
16405
|
+
autoUpdateFrustum,
|
|
16406
|
+
occlusion,
|
|
16407
|
+
size: effectiveSize,
|
|
16408
|
+
// Store size props for reset functionality
|
|
16409
|
+
_sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
|
|
16410
|
+
forceEven,
|
|
16411
|
+
// Pass mutable reference to onPointerMissed so it's free to update
|
|
16412
|
+
onPointerMissed: pointerMissed,
|
|
16413
|
+
onDragOverMissed: dragOverMissed,
|
|
16414
|
+
onDropMissed: dropMissed,
|
|
16415
|
+
onCreated: (state) => {
|
|
16416
|
+
rootState.current = state;
|
|
16417
|
+
state.events.connect?.(eventTarget() ?? divRef.current);
|
|
16418
|
+
if (eventPrefix) {
|
|
16419
|
+
state.setEvents({
|
|
16420
|
+
compute: (event, state2) => {
|
|
16421
|
+
const x = event[eventPrefix + "X"];
|
|
16422
|
+
const y = event[eventPrefix + "Y"];
|
|
16423
|
+
state2.pointer.set(x / state2.size.width * 2 - 1, -(y / state2.size.height) * 2 + 1);
|
|
16424
|
+
state2.raycaster.setFromCamera(state2.pointer, state2.camera);
|
|
16425
|
+
}
|
|
16426
|
+
});
|
|
15910
16427
|
}
|
|
15911
|
-
|
|
15912
|
-
|
|
15913
|
-
|
|
15914
|
-
|
|
16428
|
+
onCreated?.(state);
|
|
16429
|
+
}
|
|
16430
|
+
}).catch((setupError) => {
|
|
16431
|
+
if (root.current !== current) return;
|
|
16432
|
+
if (fallback != null) setFallbackVisible(true);
|
|
16433
|
+
else setError(setupError);
|
|
16434
|
+
});
|
|
16435
|
+
if (current.ready.status === "fulfilled") {
|
|
16436
|
+
current.render(
|
|
16437
|
+
/* @__PURE__ */ jsxRuntime.jsx(Bridge, { children: /* @__PURE__ */ jsxRuntime.jsx(textureStaging.ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(textureStaging.Block, { set: setBlock }), children: [
|
|
15915
16438
|
backgroundProps && /* @__PURE__ */ jsxRuntime.jsx(Environment, { ...backgroundProps }),
|
|
15916
16439
|
children ?? null
|
|
15917
16440
|
] }) }) })
|
|
15918
16441
|
);
|
|
16442
|
+
} else if (current.ready.status === "pending") {
|
|
16443
|
+
waitFor(current.ready);
|
|
15919
16444
|
}
|
|
15920
|
-
run();
|
|
15921
16445
|
}
|
|
15922
|
-
|
|
15923
|
-
|
|
15924
|
-
|
|
15925
|
-
|
|
15926
|
-
|
|
15927
|
-
|
|
16446
|
+
});
|
|
16447
|
+
textureStaging.useIsomorphicLayoutEffect(() => {
|
|
16448
|
+
const store = canvasRef.current && _roots.get(canvasRef.current)?.store;
|
|
16449
|
+
if (!store) return;
|
|
16450
|
+
const report = () => {
|
|
16451
|
+
const error2 = store.getState().error;
|
|
16452
|
+
if (error2) setError(error2);
|
|
15928
16453
|
};
|
|
16454
|
+
report();
|
|
16455
|
+
return store.subscribe(report);
|
|
16456
|
+
});
|
|
16457
|
+
React__namespace.useEffect(() => {
|
|
16458
|
+
const state = rootState.current?.get();
|
|
16459
|
+
const target = eventTarget();
|
|
16460
|
+
if (state && target && state.events.connected !== target) state.events.connect?.(target);
|
|
15929
16461
|
});
|
|
16462
|
+
const insertionMounted = React__namespace.useRef(false);
|
|
16463
|
+
const [primaryToken] = React__namespace.useState(() => ({}));
|
|
16464
|
+
const primaryKey = React__namespace.useRef(null);
|
|
16465
|
+
React__namespace.useInsertionEffect(() => {
|
|
16466
|
+
insertionMounted.current = true;
|
|
16467
|
+
if (primary && provider.webgpu) {
|
|
16468
|
+
primaryKey.current ?? (primaryKey.current = id || DEFAULT_PRIMARY);
|
|
16469
|
+
announcePrimary(primaryKey.current, primaryToken);
|
|
16470
|
+
}
|
|
16471
|
+
return () => {
|
|
16472
|
+
insertionMounted.current = false;
|
|
16473
|
+
if (primaryKey.current) markWithdrawing(primaryToken);
|
|
16474
|
+
queueMicrotask(() => {
|
|
16475
|
+
if (insertionMounted.current) return;
|
|
16476
|
+
if (primaryKey.current) withdrawPrimary(primaryKey.current, primaryToken);
|
|
16477
|
+
const current = root.current;
|
|
16478
|
+
root.current = null;
|
|
16479
|
+
current?.unmount();
|
|
16480
|
+
});
|
|
16481
|
+
};
|
|
16482
|
+
}, []);
|
|
15930
16483
|
React__namespace.useEffect(() => {
|
|
15931
16484
|
const canvas = canvasRef.current;
|
|
15932
16485
|
if (canvas) {
|
|
15933
16486
|
return () => {
|
|
15934
16487
|
if (canvas.isConnected) return;
|
|
15935
|
-
|
|
16488
|
+
const current = root.current;
|
|
15936
16489
|
root.current = null;
|
|
16490
|
+
current?.unmount();
|
|
15937
16491
|
};
|
|
15938
16492
|
}
|
|
15939
16493
|
}, []);
|
|
@@ -15944,10 +16498,10 @@ function CanvasImpl({
|
|
|
15944
16498
|
const handleHMR = () => {
|
|
15945
16499
|
queueMicrotask(() => {
|
|
15946
16500
|
const rootEntry = _roots.get(canvas);
|
|
15947
|
-
if (rootEntry?.store)
|
|
16501
|
+
if (rootEntry?.store) textureStaging.notifyRootExtensionsHmr(rootEntry.store);
|
|
15948
16502
|
});
|
|
15949
16503
|
};
|
|
15950
|
-
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/fiber.
|
|
16504
|
+
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/fiber.Bzw3s8zU.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
15951
16505
|
const hot = undefined;
|
|
15952
16506
|
hot.on("vite:afterUpdate", handleHMR);
|
|
15953
16507
|
return () => hot.off?.("vite:afterUpdate", handleHMR);
|
|
@@ -15960,7 +16514,7 @@ function CanvasImpl({
|
|
|
15960
16514
|
}
|
|
15961
16515
|
}, [hmr]);
|
|
15962
16516
|
const pointerEvents = eventSource ? "none" : "auto";
|
|
15963
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
16517
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
15964
16518
|
"div",
|
|
15965
16519
|
{
|
|
15966
16520
|
ref: divRef,
|
|
@@ -15972,21 +16526,24 @@ function CanvasImpl({
|
|
|
15972
16526
|
pointerEvents,
|
|
15973
16527
|
...style
|
|
15974
16528
|
},
|
|
15975
|
-
...
|
|
15976
|
-
children:
|
|
15977
|
-
|
|
15978
|
-
|
|
15979
|
-
|
|
15980
|
-
|
|
15981
|
-
"canvas",
|
|
15982
|
-
|
|
15983
|
-
|
|
15984
|
-
|
|
15985
|
-
|
|
15986
|
-
|
|
15987
|
-
|
|
15988
|
-
|
|
15989
|
-
|
|
16529
|
+
...divProps,
|
|
16530
|
+
children: [
|
|
16531
|
+
fallbackVisible ? (
|
|
16532
|
+
// Renderer setup failed: render the fallback as visible DOM. Inside <canvas> (below)
|
|
16533
|
+
// it exists in the tree but browsers never paint it, which is the whole bug (#3757).
|
|
16534
|
+
fallback
|
|
16535
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16536
|
+
"canvas",
|
|
16537
|
+
{
|
|
16538
|
+
ref: canvasRef,
|
|
16539
|
+
id,
|
|
16540
|
+
className: "r3f-canvas",
|
|
16541
|
+
style: { display: "block", width: "100%", height: "100%" },
|
|
16542
|
+
children: fallback
|
|
16543
|
+
}
|
|
16544
|
+
) }),
|
|
16545
|
+
gate
|
|
16546
|
+
]
|
|
15990
16547
|
}
|
|
15991
16548
|
);
|
|
15992
16549
|
}
|