@react-three/fiber 10.0.0-canary.4bc4a97 → 10.0.0-canary.4bf885a
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 +278 -0
- package/dist/extension.d.cts +1675 -0
- package/dist/extension.d.mts +1675 -0
- package/dist/extension.d.ts +1647 -0
- package/dist/extension.mjs +258 -0
- package/dist/index.cjs +984 -899
- package/dist/index.d.cts +337 -156
- package/dist/index.d.mts +337 -156
- package/dist/index.d.ts +335 -182
- package/dist/index.mjs +985 -902
- package/dist/legacy.cjs +997 -913
- package/dist/legacy.d.cts +358 -209
- package/dist/legacy.d.mts +358 -209
- package/dist/legacy.d.ts +356 -233
- package/dist/legacy.mjs +998 -916
- package/dist/webgpu/index.cjs +899 -736
- package/dist/webgpu/index.d.cts +412 -262
- package/dist/webgpu/index.d.mts +412 -262
- package/dist/webgpu/index.d.ts +410 -288
- package/dist/webgpu/index.mjs +900 -739
- package/package.json +7 -2
package/dist/legacy.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as three from 'three';
|
|
2
|
-
import { WebGLCubeRenderTarget, WebGLRenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType,
|
|
2
|
+
import { WebGLCubeRenderTarget, WebGLRenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType, TextureLoader, Texture as Texture$1, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Vector3, Vector2, Raycaster, OrthographicCamera, PerspectiveCamera, Scene, PCFShadowMap, VSMShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGLRenderer, HalfFloatType, Color } from 'three';
|
|
3
3
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import React__default, { useRef, useMemo, useLayoutEffect, useEffect,
|
|
5
|
+
import React__default, { useContext, useRef, useMemo, useLayoutEffect, useEffect, useImperativeHandle, useCallback, useState } from 'react';
|
|
6
6
|
import useMeasure from 'react-use-measure';
|
|
7
7
|
import { useFiber, useContextBridge, traverseFiber, FiberProvider } from 'its-fine';
|
|
8
8
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
@@ -11,6 +11,7 @@ export { Scheduler, getScheduler } from '@pmndrs/scheduler';
|
|
|
11
11
|
import Tb, { unstable_getCurrentPriorityLevel, unstable_IdlePriority, unstable_LowPriority, unstable_NormalPriority, unstable_UserBlockingPriority, unstable_ImmediatePriority, unstable_scheduleCallback } from 'scheduler';
|
|
12
12
|
import { GroundedSkybox } from 'three/examples/jsm/objects/GroundedSkybox.js';
|
|
13
13
|
import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
|
|
14
|
+
import { HDRCubeTextureLoader } from 'three/examples/jsm/loaders/HDRCubeTextureLoader.js';
|
|
14
15
|
import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js';
|
|
15
16
|
import { UltraHDRLoader } from 'three/examples/jsm/loaders/UltraHDRLoader.js';
|
|
16
17
|
import { GainMapLoader } from '@monogrid/gainmap-js';
|
|
@@ -30,16 +31,14 @@ function _mergeNamespaces(n, m) {
|
|
|
30
31
|
|
|
31
32
|
const R3F_BUILD_LEGACY = true;
|
|
32
33
|
const R3F_BUILD_WEBGPU = false;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
};
|
|
38
|
-
const WebGPURenderer = class WebGPURenderer2 {
|
|
34
|
+
async function loadInspector() {
|
|
35
|
+
throw new Error("Inspector is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
36
|
+
}
|
|
37
|
+
class WebGPURenderer {
|
|
39
38
|
constructor() {
|
|
40
39
|
throw new Error("WebGPURenderer is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
41
40
|
}
|
|
42
|
-
}
|
|
41
|
+
}
|
|
43
42
|
const RenderTarget = null;
|
|
44
43
|
const CubeRenderTarget = null;
|
|
45
44
|
|
|
@@ -47,12 +46,12 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
47
46
|
__proto__: null,
|
|
48
47
|
CubeRenderTarget: CubeRenderTarget,
|
|
49
48
|
CubeRenderTargetCompat: WebGLCubeRenderTarget,
|
|
50
|
-
Inspector: Inspector,
|
|
51
49
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
52
50
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
53
51
|
RenderTarget: RenderTarget,
|
|
54
52
|
RenderTargetCompat: WebGLRenderTarget,
|
|
55
|
-
WebGPURenderer: WebGPURenderer
|
|
53
|
+
WebGPURenderer: WebGPURenderer,
|
|
54
|
+
loadInspector: loadInspector
|
|
56
55
|
}, [three]);
|
|
57
56
|
|
|
58
57
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -299,7 +298,6 @@ function prepare(target, root, type, props) {
|
|
|
299
298
|
}
|
|
300
299
|
function invalidateInstance(instance) {
|
|
301
300
|
if (!instance.parent) return;
|
|
302
|
-
instance.props.onUpdate?.(instance.object);
|
|
303
301
|
const state = instance.root?.getState?.();
|
|
304
302
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
305
303
|
}
|
|
@@ -515,8 +513,10 @@ function hasVisibilityHandlers(handlers) {
|
|
|
515
513
|
}
|
|
516
514
|
|
|
517
515
|
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
518
|
-
function fromRef(ref) {
|
|
519
|
-
|
|
516
|
+
function fromRef(ref, transform) {
|
|
517
|
+
const marker = { [FROM_REF]: ref };
|
|
518
|
+
if (transform) marker.transform = transform;
|
|
519
|
+
return marker;
|
|
520
520
|
}
|
|
521
521
|
function isFromRef(value) {
|
|
522
522
|
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
@@ -530,6 +530,63 @@ function isOnce(value) {
|
|
|
530
530
|
return value !== null && typeof value === "object" && ONCE in value;
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
+
const shownNotices = /* @__PURE__ */ new Set();
|
|
534
|
+
function notifyDepreciated({ heading, body, link }) {
|
|
535
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
if (shownNotices.has(heading)) return;
|
|
539
|
+
shownNotices.add(heading);
|
|
540
|
+
const caller = getCallerFrame();
|
|
541
|
+
if (caller) {
|
|
542
|
+
console.log();
|
|
543
|
+
}
|
|
544
|
+
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
545
|
+
if (caller) {
|
|
546
|
+
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
547
|
+
}
|
|
548
|
+
if (body || link) {
|
|
549
|
+
let message = "";
|
|
550
|
+
if (body) message += body;
|
|
551
|
+
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
552
|
+
console.warn(`%c${message}`, "font-weight: bold;");
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
function getCallerFrame(depth = 3) {
|
|
556
|
+
const stack = new Error().stack;
|
|
557
|
+
if (!stack) return null;
|
|
558
|
+
const lines = stack.split("\n");
|
|
559
|
+
const frame = lines[depth];
|
|
560
|
+
if (!frame) return null;
|
|
561
|
+
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
562
|
+
if (!match) {
|
|
563
|
+
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
564
|
+
}
|
|
565
|
+
if (!match) return null;
|
|
566
|
+
const [, fn, url, line] = match;
|
|
567
|
+
return {
|
|
568
|
+
functionName: fn ?? "<anonymous>",
|
|
569
|
+
location: formatLocation(url, Number(line))
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function formatLocation(url, line) {
|
|
573
|
+
const clean = url.split("?")[0];
|
|
574
|
+
const file = clean.split("/").pop() ?? clean;
|
|
575
|
+
return `${file}:${line}`;
|
|
576
|
+
}
|
|
577
|
+
function notifyAlpha({ message, link }) {
|
|
578
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (shownNotices.has(message)) return;
|
|
582
|
+
shownNotices.add(message);
|
|
583
|
+
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
584
|
+
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
585
|
+
{
|
|
586
|
+
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
533
590
|
const RESERVED_PROPS = [
|
|
534
591
|
"children",
|
|
535
592
|
"key",
|
|
@@ -539,7 +596,6 @@ const RESERVED_PROPS = [
|
|
|
539
596
|
"dispose",
|
|
540
597
|
"attach",
|
|
541
598
|
"object",
|
|
542
|
-
"onUpdate",
|
|
543
599
|
// Behavior flags
|
|
544
600
|
"dispose"
|
|
545
601
|
];
|
|
@@ -617,11 +673,9 @@ function diffProps(instance, newProps) {
|
|
|
617
673
|
for (const prop in instance.props) {
|
|
618
674
|
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
619
675
|
const { root, key } = resolve(instance.object, prop);
|
|
620
|
-
if (
|
|
676
|
+
if (typeof root?.constructor === "function") {
|
|
621
677
|
const ctor = getMemoizedPrototype(root);
|
|
622
678
|
if (!is.und(ctor)) changedProps[prop] = ctor[key];
|
|
623
|
-
} else {
|
|
624
|
-
changedProps[prop] = 0;
|
|
625
679
|
}
|
|
626
680
|
}
|
|
627
681
|
return changedProps;
|
|
@@ -633,6 +687,13 @@ function applyProps(object, props) {
|
|
|
633
687
|
for (const prop in props) {
|
|
634
688
|
const value = props[prop];
|
|
635
689
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
690
|
+
if (prop === "onUpdate") {
|
|
691
|
+
notifyDepreciated({
|
|
692
|
+
heading: "onUpdate is no longer an R3F prop",
|
|
693
|
+
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.",
|
|
694
|
+
link: "https://docs.pmnd.rs/react-three-fiber/migration/v10#onupdate-removed"
|
|
695
|
+
});
|
|
696
|
+
}
|
|
636
697
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
637
698
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
638
699
|
else delete instance.handlers[prop];
|
|
@@ -738,682 +799,378 @@ function applyProps(object, props) {
|
|
|
738
799
|
return object;
|
|
739
800
|
}
|
|
740
801
|
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
if (
|
|
747
|
-
|
|
748
|
-
const caller = getCallerFrame();
|
|
749
|
-
if (caller) {
|
|
750
|
-
console.log();
|
|
751
|
-
}
|
|
752
|
-
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
753
|
-
if (caller) {
|
|
754
|
-
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
755
|
-
}
|
|
756
|
-
if (body || link) {
|
|
757
|
-
let message = "";
|
|
758
|
-
if (body) message += body;
|
|
759
|
-
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
760
|
-
console.warn(`%c${message}`, "font-weight: bold;");
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
function getCallerFrame(depth = 3) {
|
|
764
|
-
const stack = new Error().stack;
|
|
765
|
-
if (!stack) return null;
|
|
766
|
-
const lines = stack.split("\n");
|
|
767
|
-
const frame = lines[depth];
|
|
768
|
-
if (!frame) return null;
|
|
769
|
-
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
770
|
-
if (!match) {
|
|
771
|
-
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
772
|
-
}
|
|
773
|
-
if (!match) return null;
|
|
774
|
-
const [, fn, url, line] = match;
|
|
775
|
-
return {
|
|
776
|
-
functionName: fn ?? "<anonymous>",
|
|
777
|
-
location: formatLocation(url, Number(line))
|
|
778
|
-
};
|
|
802
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
803
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
804
|
+
|
|
805
|
+
function useStore() {
|
|
806
|
+
const store = useContext(context);
|
|
807
|
+
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
808
|
+
return store;
|
|
779
809
|
}
|
|
780
|
-
function
|
|
781
|
-
|
|
782
|
-
const file = clean.split("/").pop() ?? clean;
|
|
783
|
-
return `${file}:${line}`;
|
|
810
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
811
|
+
return useStore()(selector, equalityFn);
|
|
784
812
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
if (
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
813
|
+
|
|
814
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
815
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
816
|
+
function getLoader$1(Proto) {
|
|
817
|
+
if (isConstructor$1(Proto)) {
|
|
818
|
+
let loader = memoizedLoaders.get(Proto);
|
|
819
|
+
if (!loader) {
|
|
820
|
+
loader = new Proto();
|
|
821
|
+
memoizedLoaders.set(Proto, loader);
|
|
822
|
+
}
|
|
823
|
+
return loader;
|
|
795
824
|
}
|
|
825
|
+
return Proto;
|
|
796
826
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
827
|
+
function loadingFn(extensions, onProgress) {
|
|
828
|
+
return function(Proto, input) {
|
|
829
|
+
const loader = getLoader$1(Proto);
|
|
830
|
+
if (extensions) extensions(loader);
|
|
831
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
832
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
833
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
834
|
+
return data;
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
return new Promise(
|
|
838
|
+
(res, reject) => loader.load(
|
|
839
|
+
input,
|
|
840
|
+
(data) => {
|
|
841
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
842
|
+
res(data);
|
|
843
|
+
},
|
|
844
|
+
onProgress,
|
|
845
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
846
|
+
)
|
|
847
|
+
);
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
851
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
852
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
853
|
+
const fn = loadingFn(extensions, onProgress);
|
|
854
|
+
const results = cacheKeys.map(
|
|
855
|
+
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
856
|
+
);
|
|
857
|
+
const stableRef = useRef(null);
|
|
858
|
+
const previous = stableRef.current;
|
|
859
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
860
|
+
stableRef.current = stable;
|
|
861
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
803
862
|
}
|
|
863
|
+
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
864
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
865
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
866
|
+
cacheKeys.forEach(
|
|
867
|
+
(key, index) => preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
868
|
+
);
|
|
869
|
+
};
|
|
870
|
+
useLoader.clear = function(loader, input, cacheKey) {
|
|
871
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
872
|
+
cacheKeys.forEach((key) => clear([loader, key]));
|
|
873
|
+
};
|
|
874
|
+
useLoader.loader = getLoader$1;
|
|
804
875
|
|
|
805
|
-
|
|
806
|
-
const
|
|
807
|
-
const
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
876
|
+
function useFrame$1(callback, priorityOrOptions) {
|
|
877
|
+
const store = React.useContext(context);
|
|
878
|
+
const isInsideCanvas = store !== null;
|
|
879
|
+
const scheduler = getScheduler();
|
|
880
|
+
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
881
|
+
id: priorityOrOptions.id,
|
|
882
|
+
phase: priorityOrOptions.phase,
|
|
883
|
+
priority: priorityOrOptions.priority,
|
|
884
|
+
fps: priorityOrOptions.fps,
|
|
885
|
+
drop: priorityOrOptions.drop,
|
|
886
|
+
enabled: priorityOrOptions.enabled,
|
|
887
|
+
before: priorityOrOptions.before,
|
|
888
|
+
after: priorityOrOptions.after
|
|
889
|
+
}) : "";
|
|
890
|
+
const options = React.useMemo(() => {
|
|
891
|
+
return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
|
|
892
|
+
}, [optionsKey]);
|
|
893
|
+
const reactId = React.useId();
|
|
894
|
+
const id = options.id ?? reactId;
|
|
895
|
+
const callbackRef = useMutableCallback(callback);
|
|
896
|
+
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
897
|
+
useIsomorphicLayoutEffect(() => {
|
|
898
|
+
if (!callback) return;
|
|
899
|
+
if (isInsideCanvas) {
|
|
900
|
+
const state = store.getState();
|
|
901
|
+
const rootId = state.internal.rootId;
|
|
902
|
+
if (isLegacyPriority) {
|
|
903
|
+
state.internal.priority++;
|
|
904
|
+
let parentRoot = state.previousRoot;
|
|
905
|
+
while (parentRoot) {
|
|
906
|
+
const parentState = parentRoot.getState();
|
|
907
|
+
if (parentState?.internal) parentState.internal.priority++;
|
|
908
|
+
parentRoot = parentState?.previousRoot;
|
|
909
|
+
}
|
|
910
|
+
notifyDepreciated({
|
|
911
|
+
heading: "useFrame with numeric priority is deprecated",
|
|
912
|
+
body: 'Using useFrame(callback, number) to control render order is deprecated.\n\nFor custom rendering, use: useFrame(callback, { phase: "render" })\nFor execution order within update phase, use: useFrame(callback, { priority: number })',
|
|
913
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
914
|
+
});
|
|
825
915
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
inspector: null,
|
|
854
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
855
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
856
|
-
textureColorSpace: SRGBColorSpace,
|
|
857
|
-
isLegacy: false,
|
|
858
|
-
webGPUSupported: false,
|
|
859
|
-
isNative: false,
|
|
860
|
-
controls: null,
|
|
861
|
-
pointer,
|
|
862
|
-
mouse: pointer,
|
|
863
|
-
frameloop: "always",
|
|
864
|
-
onPointerMissed: void 0,
|
|
865
|
-
onDragOverMissed: void 0,
|
|
866
|
-
onDropMissed: void 0,
|
|
867
|
-
performance: {
|
|
868
|
-
current: 1,
|
|
869
|
-
min: 0.5,
|
|
870
|
-
max: 1,
|
|
871
|
-
debounce: 200,
|
|
872
|
-
regress: () => {
|
|
873
|
-
const state2 = get();
|
|
874
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
875
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
876
|
-
performanceTimeout = setTimeout(
|
|
877
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
878
|
-
state2.performance.debounce
|
|
879
|
-
);
|
|
880
|
-
}
|
|
881
|
-
},
|
|
882
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
883
|
-
viewport: {
|
|
884
|
-
initialDpr: 0,
|
|
885
|
-
dpr: 0,
|
|
886
|
-
width: 0,
|
|
887
|
-
height: 0,
|
|
888
|
-
top: 0,
|
|
889
|
-
left: 0,
|
|
890
|
-
aspect: 0,
|
|
891
|
-
distance: 0,
|
|
892
|
-
factor: 0,
|
|
893
|
-
getCurrentViewport
|
|
894
|
-
},
|
|
895
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
896
|
-
setSize: (width, height, top, left) => {
|
|
897
|
-
const state2 = get();
|
|
898
|
-
if (width === void 0) {
|
|
899
|
-
set({ _sizeImperative: false });
|
|
900
|
-
if (state2._sizeProps) {
|
|
901
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
902
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
903
|
-
const currentSize = state2.size;
|
|
904
|
-
const newSize = {
|
|
905
|
-
width: propW ?? currentSize.width,
|
|
906
|
-
height: propH ?? currentSize.height,
|
|
907
|
-
top: currentSize.top,
|
|
908
|
-
left: currentSize.left
|
|
909
|
-
};
|
|
910
|
-
set((s) => ({
|
|
911
|
-
size: newSize,
|
|
912
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
913
|
-
}));
|
|
914
|
-
getScheduler().invalidate();
|
|
916
|
+
const wrappedCallback = (frameState, delta) => {
|
|
917
|
+
const localState = store.getState();
|
|
918
|
+
const mergedState = {
|
|
919
|
+
...localState,
|
|
920
|
+
time: frameState.time,
|
|
921
|
+
delta: frameState.delta,
|
|
922
|
+
elapsed: frameState.elapsed,
|
|
923
|
+
frame: frameState.frame
|
|
924
|
+
};
|
|
925
|
+
callbackRef.current?.(mergedState, delta);
|
|
926
|
+
};
|
|
927
|
+
const unregister = scheduler.register(wrappedCallback, {
|
|
928
|
+
id,
|
|
929
|
+
rootId,
|
|
930
|
+
...options
|
|
931
|
+
});
|
|
932
|
+
return () => {
|
|
933
|
+
unregister();
|
|
934
|
+
if (isLegacyPriority) {
|
|
935
|
+
const currentState = store.getState();
|
|
936
|
+
if (currentState.internal) {
|
|
937
|
+
currentState.internal.priority--;
|
|
938
|
+
let parentRoot = currentState.previousRoot;
|
|
939
|
+
while (parentRoot) {
|
|
940
|
+
const parentState = parentRoot.getState();
|
|
941
|
+
if (parentState?.internal) parentState.internal.priority--;
|
|
942
|
+
parentRoot = parentState?.previousRoot;
|
|
915
943
|
}
|
|
916
944
|
}
|
|
917
|
-
return;
|
|
918
945
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
946
|
+
};
|
|
947
|
+
} else {
|
|
948
|
+
return scheduler.register(
|
|
949
|
+
(state, delta) => {
|
|
950
|
+
const frameState = state;
|
|
951
|
+
if (!frameState.renderer) return;
|
|
952
|
+
callbackRef.current?.(frameState, delta);
|
|
953
|
+
},
|
|
954
|
+
{ id, ...options }
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
}, [store, scheduler, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
958
|
+
const isPaused = React.useSyncExternalStore(
|
|
959
|
+
// Subscribe function
|
|
960
|
+
React.useCallback(
|
|
961
|
+
(onStoreChange) => {
|
|
962
|
+
return getScheduler().subscribeJobState(id, onStoreChange);
|
|
930
963
|
},
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
964
|
+
[id]
|
|
965
|
+
),
|
|
966
|
+
// getSnapshot function
|
|
967
|
+
React.useCallback(() => getScheduler().isJobPaused(id), [id]),
|
|
968
|
+
// getServerSnapshot function (SSR)
|
|
969
|
+
React.useCallback(() => false, [])
|
|
970
|
+
);
|
|
971
|
+
const controls = React.useMemo(() => {
|
|
972
|
+
const scheduler2 = getScheduler();
|
|
973
|
+
return {
|
|
974
|
+
/** The job's unique ID */
|
|
975
|
+
id,
|
|
976
|
+
/**
|
|
977
|
+
* Access to the global scheduler for frame loop control.
|
|
978
|
+
* Use for controlling the entire frame loop, adding phases, etc.
|
|
979
|
+
*/
|
|
980
|
+
scheduler: scheduler2,
|
|
981
|
+
/**
|
|
982
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
983
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
984
|
+
*/
|
|
985
|
+
get rootId() {
|
|
986
|
+
return getScheduler().getJobRootId(id);
|
|
938
987
|
},
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
internal.subscribers.push({ ref, priority, store });
|
|
982
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
983
|
-
return () => {
|
|
984
|
-
const internal2 = get().internal;
|
|
985
|
-
if (internal2?.subscribers) {
|
|
986
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
987
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
988
|
-
}
|
|
989
|
-
};
|
|
990
|
-
},
|
|
991
|
-
// Renderer Storage (single source of truth)
|
|
992
|
-
actualRenderer: null,
|
|
993
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
994
|
-
scheduler: null
|
|
995
|
-
}
|
|
988
|
+
/**
|
|
989
|
+
* Manually step this job only.
|
|
990
|
+
* Bypasses FPS limiting - always runs.
|
|
991
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
992
|
+
*/
|
|
993
|
+
step: (timestamp) => {
|
|
994
|
+
getScheduler().stepJob(id, timestamp);
|
|
995
|
+
},
|
|
996
|
+
/**
|
|
997
|
+
* Manually step ALL jobs in the scheduler.
|
|
998
|
+
* Useful for frameloop='never' mode.
|
|
999
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1000
|
+
*/
|
|
1001
|
+
stepAll: (timestamp) => {
|
|
1002
|
+
getScheduler().step(timestamp);
|
|
1003
|
+
},
|
|
1004
|
+
/**
|
|
1005
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1006
|
+
*/
|
|
1007
|
+
invalidate: (frames, stackFrames) => {
|
|
1008
|
+
const scheduler3 = getScheduler();
|
|
1009
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1010
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1011
|
+
},
|
|
1012
|
+
/**
|
|
1013
|
+
* Pause this job (set enabled=false).
|
|
1014
|
+
* Job remains registered but won't run.
|
|
1015
|
+
*/
|
|
1016
|
+
pause: () => {
|
|
1017
|
+
getScheduler().pauseJob(id);
|
|
1018
|
+
},
|
|
1019
|
+
/**
|
|
1020
|
+
* Resume this job (set enabled=true).
|
|
1021
|
+
*/
|
|
1022
|
+
resume: () => {
|
|
1023
|
+
getScheduler().resumeJob(id);
|
|
1024
|
+
},
|
|
1025
|
+
/**
|
|
1026
|
+
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1027
|
+
* No need for forceUpdate() in your components.
|
|
1028
|
+
*/
|
|
1029
|
+
isPaused
|
|
996
1030
|
};
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
Object.defineProperty(state, "gl", {
|
|
1001
|
-
get() {
|
|
1002
|
-
const currentState = rootStore.getState();
|
|
1003
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1004
|
-
const stack = new Error().stack || "";
|
|
1005
|
-
if (!isInternalRendererAccess(stack)) {
|
|
1006
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1007
|
-
notifyDepreciated({
|
|
1008
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1009
|
-
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
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
return currentState.internal.actualRenderer;
|
|
1014
|
-
},
|
|
1015
|
-
set(value) {
|
|
1016
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1017
|
-
},
|
|
1018
|
-
enumerable: true,
|
|
1019
|
-
configurable: true
|
|
1020
|
-
});
|
|
1021
|
-
Object.defineProperty(state, "renderer", {
|
|
1022
|
-
get() {
|
|
1023
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1024
|
-
},
|
|
1025
|
-
set(value) {
|
|
1026
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1027
|
-
},
|
|
1028
|
-
enumerable: true,
|
|
1029
|
-
configurable: true
|
|
1030
|
-
});
|
|
1031
|
-
let oldScene = state.scene;
|
|
1032
|
-
rootStore.subscribe(() => {
|
|
1033
|
-
const currentState = rootStore.getState();
|
|
1034
|
-
const { scene, rootScene, set } = currentState;
|
|
1035
|
-
if (scene !== oldScene) {
|
|
1036
|
-
oldScene = scene;
|
|
1037
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1038
|
-
set({ rootScene: scene });
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
});
|
|
1042
|
-
let oldSize = state.size;
|
|
1043
|
-
let oldDpr = state.viewport.dpr;
|
|
1044
|
-
let oldCamera = state.camera;
|
|
1045
|
-
rootStore.subscribe(() => {
|
|
1046
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1047
|
-
const actualRenderer = internal.actualRenderer;
|
|
1048
|
-
const canvasTarget = internal.canvasTarget;
|
|
1049
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1050
|
-
oldSize = size;
|
|
1051
|
-
oldDpr = viewport.dpr;
|
|
1052
|
-
updateCamera(camera, size);
|
|
1053
|
-
if (internal.isSecondary && canvasTarget) {
|
|
1054
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1055
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1056
|
-
} else {
|
|
1057
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1058
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1059
|
-
if (canvasTarget) {
|
|
1060
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1061
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
if (camera !== oldCamera) {
|
|
1066
|
-
oldCamera = camera;
|
|
1067
|
-
const { rootScene } = rootStore.getState();
|
|
1068
|
-
if (camera && rootScene && !camera.parent) {
|
|
1069
|
-
rootScene.add(camera);
|
|
1070
|
-
}
|
|
1071
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1072
|
-
const currentState = rootStore.getState();
|
|
1073
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1074
|
-
updateFrustum(camera, currentState.frustum);
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
});
|
|
1078
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
1079
|
-
return rootStore;
|
|
1080
|
-
};
|
|
1031
|
+
}, [id, isPaused]);
|
|
1032
|
+
return controls;
|
|
1033
|
+
}
|
|
1081
1034
|
|
|
1082
|
-
const
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
if (
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1035
|
+
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1036
|
+
function getUrls(input) {
|
|
1037
|
+
if (typeof input === "string") return [input];
|
|
1038
|
+
if (Array.isArray(input)) return input;
|
|
1039
|
+
return Object.values(input);
|
|
1040
|
+
}
|
|
1041
|
+
function inputSignature(input) {
|
|
1042
|
+
if (typeof input === "string") return input;
|
|
1043
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1044
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1045
|
+
}
|
|
1046
|
+
function allUrlsCached(urls, textureCache) {
|
|
1047
|
+
return urls.every((url) => textureCache.has(url));
|
|
1048
|
+
}
|
|
1049
|
+
function buildFromCache(input, textureCache) {
|
|
1050
|
+
if (typeof input === "string") {
|
|
1051
|
+
return textureCache.get(input);
|
|
1052
|
+
} else if (Array.isArray(input)) {
|
|
1053
|
+
return input.map((url) => textureCache.get(url));
|
|
1054
|
+
} else {
|
|
1055
|
+
const result = {};
|
|
1056
|
+
const objInput = input;
|
|
1057
|
+
for (const key in objInput) {
|
|
1058
|
+
result[key] = textureCache.get(objInput[key]);
|
|
1090
1059
|
}
|
|
1091
|
-
return
|
|
1060
|
+
return result;
|
|
1092
1061
|
}
|
|
1093
|
-
return Proto;
|
|
1094
1062
|
}
|
|
1095
|
-
function
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1063
|
+
function useTexture(input, optionsOrOnLoad) {
|
|
1064
|
+
const renderer = useThree$1((state) => state.internal.actualRenderer);
|
|
1065
|
+
const store = useStore();
|
|
1066
|
+
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1067
|
+
const { onLoad, cache = true } = options;
|
|
1068
|
+
const onLoadRef = useRef(onLoad);
|
|
1069
|
+
onLoadRef.current = onLoad;
|
|
1070
|
+
const onLoadCalledForRef = useRef(null);
|
|
1071
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
1072
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
1073
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1074
|
+
const cachedResult = useMemo(() => {
|
|
1075
|
+
if (!cache) return null;
|
|
1076
|
+
const textures = store.getState().textures;
|
|
1077
|
+
if (!allUrlsCached(urls, textures)) return null;
|
|
1078
|
+
return buildFromCache(stableInput, textures);
|
|
1079
|
+
}, [cache, urls, stableInput, store]);
|
|
1080
|
+
const loadedTextures = useLoader(
|
|
1081
|
+
TextureLoader,
|
|
1082
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1083
|
+
);
|
|
1084
|
+
const mappedTextures = useMemo(() => {
|
|
1085
|
+
if (cachedResult) return cachedResult;
|
|
1086
|
+
if (IsObject(stableInput)) {
|
|
1087
|
+
const keyed = {};
|
|
1088
|
+
const textureArray = loadedTextures;
|
|
1089
|
+
let i = 0;
|
|
1090
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1091
|
+
return keyed;
|
|
1092
|
+
} else {
|
|
1093
|
+
return loadedTextures;
|
|
1094
|
+
}
|
|
1095
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1096
|
+
useLayoutEffect(() => {
|
|
1097
|
+
if (cachedResult) return;
|
|
1098
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
1099
|
+
onLoadCalledForRef.current = inputKey;
|
|
1100
|
+
onLoadRef.current?.(mappedTextures);
|
|
1101
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
1102
|
+
useEffect(() => {
|
|
1103
|
+
if (cachedResult) return;
|
|
1104
|
+
if ("initTexture" in renderer) {
|
|
1105
|
+
let textureArray = [];
|
|
1106
|
+
if (Array.isArray(loadedTextures)) {
|
|
1107
|
+
textureArray = loadedTextures;
|
|
1108
|
+
} else if (loadedTextures instanceof Texture$1) {
|
|
1109
|
+
textureArray = [loadedTextures];
|
|
1110
|
+
} else if (IsObject(loadedTextures)) {
|
|
1111
|
+
textureArray = Object.values(loadedTextures);
|
|
1112
|
+
}
|
|
1113
|
+
textureArray.forEach((texture) => {
|
|
1114
|
+
if (texture instanceof Texture$1) {
|
|
1115
|
+
renderer.initTexture(texture);
|
|
1116
|
+
}
|
|
1103
1117
|
});
|
|
1104
1118
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1119
|
+
}, [renderer, loadedTextures, cachedResult]);
|
|
1120
|
+
useEffect(() => {
|
|
1121
|
+
if (!cache) return;
|
|
1122
|
+
const urlTextureMap = [];
|
|
1123
|
+
if (typeof stableInput === "string") {
|
|
1124
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1125
|
+
} else if (Array.isArray(stableInput)) {
|
|
1126
|
+
const textureArray = mappedTextures;
|
|
1127
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1128
|
+
} else if (IsObject(stableInput)) {
|
|
1129
|
+
const textureRecord = mappedTextures;
|
|
1130
|
+
for (const key in stableInput) {
|
|
1131
|
+
const url = stableInput[key];
|
|
1132
|
+
urlTextureMap.push([url, textureRecord[key]]);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
store.setState((state) => {
|
|
1136
|
+
const refs = new Map(state._textureRefs);
|
|
1137
|
+
let textures = state.textures;
|
|
1138
|
+
let added = false;
|
|
1139
|
+
for (const [url, texture] of urlTextureMap) {
|
|
1140
|
+
if (!textures.has(url)) {
|
|
1141
|
+
if (!added) {
|
|
1142
|
+
textures = new Map(textures);
|
|
1143
|
+
added = true;
|
|
1144
|
+
}
|
|
1145
|
+
textures.set(url, texture);
|
|
1146
|
+
}
|
|
1147
|
+
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
1148
|
+
}
|
|
1149
|
+
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
1150
|
+
});
|
|
1151
|
+
return () => store.setState((state) => {
|
|
1152
|
+
const refs = new Map(state._textureRefs);
|
|
1153
|
+
for (const [url] of urlTextureMap) {
|
|
1154
|
+
const next = (refs.get(url) ?? 0) - 1;
|
|
1155
|
+
if (next <= 0) refs.delete(url);
|
|
1156
|
+
else refs.set(url, next);
|
|
1157
|
+
}
|
|
1158
|
+
return { _textureRefs: refs };
|
|
1159
|
+
});
|
|
1160
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1161
|
+
return mappedTextures;
|
|
1126
1162
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
const
|
|
1136
|
-
|
|
1137
|
-
};
|
|
1138
|
-
useLoader.loader = getLoader$1;
|
|
1139
|
-
|
|
1140
|
-
function useFrame(callback, priorityOrOptions) {
|
|
1141
|
-
const store = React.useContext(context);
|
|
1142
|
-
const isInsideCanvas = store !== null;
|
|
1143
|
-
const scheduler = getScheduler();
|
|
1144
|
-
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
1145
|
-
id: priorityOrOptions.id,
|
|
1146
|
-
phase: priorityOrOptions.phase,
|
|
1147
|
-
priority: priorityOrOptions.priority,
|
|
1148
|
-
fps: priorityOrOptions.fps,
|
|
1149
|
-
drop: priorityOrOptions.drop,
|
|
1150
|
-
enabled: priorityOrOptions.enabled,
|
|
1151
|
-
before: priorityOrOptions.before,
|
|
1152
|
-
after: priorityOrOptions.after
|
|
1153
|
-
}) : "";
|
|
1154
|
-
const options = React.useMemo(() => {
|
|
1155
|
-
return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
|
|
1156
|
-
}, [optionsKey]);
|
|
1157
|
-
const reactId = React.useId();
|
|
1158
|
-
const id = options.id ?? reactId;
|
|
1159
|
-
const callbackRef = useMutableCallback(callback);
|
|
1160
|
-
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
1161
|
-
useIsomorphicLayoutEffect(() => {
|
|
1162
|
-
if (!callback) return;
|
|
1163
|
-
if (isInsideCanvas) {
|
|
1164
|
-
const state = store.getState();
|
|
1165
|
-
const rootId = state.internal.rootId;
|
|
1166
|
-
if (isLegacyPriority) {
|
|
1167
|
-
state.internal.priority++;
|
|
1168
|
-
let parentRoot = state.previousRoot;
|
|
1169
|
-
while (parentRoot) {
|
|
1170
|
-
const parentState = parentRoot.getState();
|
|
1171
|
-
if (parentState?.internal) parentState.internal.priority++;
|
|
1172
|
-
parentRoot = parentState?.previousRoot;
|
|
1173
|
-
}
|
|
1174
|
-
notifyDepreciated({
|
|
1175
|
-
heading: "useFrame with numeric priority is deprecated",
|
|
1176
|
-
body: 'Using useFrame(callback, number) to control render order is deprecated.\n\nFor custom rendering, use: useFrame(callback, { phase: "render" })\nFor execution order within update phase, use: useFrame(callback, { priority: number })',
|
|
1177
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1178
|
-
});
|
|
1179
|
-
}
|
|
1180
|
-
const wrappedCallback = (frameState, delta) => {
|
|
1181
|
-
const localState = store.getState();
|
|
1182
|
-
const mergedState = {
|
|
1183
|
-
...localState,
|
|
1184
|
-
time: frameState.time,
|
|
1185
|
-
delta: frameState.delta,
|
|
1186
|
-
elapsed: frameState.elapsed,
|
|
1187
|
-
frame: frameState.frame
|
|
1188
|
-
};
|
|
1189
|
-
callbackRef.current?.(mergedState, delta);
|
|
1190
|
-
};
|
|
1191
|
-
const unregister = scheduler.register(wrappedCallback, {
|
|
1192
|
-
id,
|
|
1193
|
-
rootId,
|
|
1194
|
-
...options
|
|
1195
|
-
});
|
|
1196
|
-
return () => {
|
|
1197
|
-
unregister();
|
|
1198
|
-
if (isLegacyPriority) {
|
|
1199
|
-
const currentState = store.getState();
|
|
1200
|
-
if (currentState.internal) {
|
|
1201
|
-
currentState.internal.priority--;
|
|
1202
|
-
let parentRoot = currentState.previousRoot;
|
|
1203
|
-
while (parentRoot) {
|
|
1204
|
-
const parentState = parentRoot.getState();
|
|
1205
|
-
if (parentState?.internal) parentState.internal.priority--;
|
|
1206
|
-
parentRoot = parentState?.previousRoot;
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
};
|
|
1211
|
-
} else {
|
|
1212
|
-
return scheduler.register(
|
|
1213
|
-
(state, delta) => {
|
|
1214
|
-
const frameState = state;
|
|
1215
|
-
if (!frameState.renderer) return;
|
|
1216
|
-
callbackRef.current?.(frameState, delta);
|
|
1217
|
-
},
|
|
1218
|
-
{ id, ...options }
|
|
1219
|
-
);
|
|
1220
|
-
}
|
|
1221
|
-
}, [store, scheduler, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
1222
|
-
const isPaused = React.useSyncExternalStore(
|
|
1223
|
-
// Subscribe function
|
|
1224
|
-
React.useCallback(
|
|
1225
|
-
(onStoreChange) => {
|
|
1226
|
-
return getScheduler().subscribeJobState(id, onStoreChange);
|
|
1227
|
-
},
|
|
1228
|
-
[id]
|
|
1229
|
-
),
|
|
1230
|
-
// getSnapshot function
|
|
1231
|
-
React.useCallback(() => getScheduler().isJobPaused(id), [id]),
|
|
1232
|
-
// getServerSnapshot function (SSR)
|
|
1233
|
-
React.useCallback(() => false, [])
|
|
1234
|
-
);
|
|
1235
|
-
const controls = React.useMemo(() => {
|
|
1236
|
-
const scheduler2 = getScheduler();
|
|
1237
|
-
return {
|
|
1238
|
-
/** The job's unique ID */
|
|
1239
|
-
id,
|
|
1240
|
-
/**
|
|
1241
|
-
* Access to the global scheduler for frame loop control.
|
|
1242
|
-
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1243
|
-
*/
|
|
1244
|
-
scheduler: scheduler2,
|
|
1245
|
-
/**
|
|
1246
|
-
* Manually step this job only.
|
|
1247
|
-
* Bypasses FPS limiting - always runs.
|
|
1248
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1249
|
-
*/
|
|
1250
|
-
step: (timestamp) => {
|
|
1251
|
-
getScheduler().stepJob(id, timestamp);
|
|
1252
|
-
},
|
|
1253
|
-
/**
|
|
1254
|
-
* Manually step ALL jobs in the scheduler.
|
|
1255
|
-
* Useful for frameloop='never' mode.
|
|
1256
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1257
|
-
*/
|
|
1258
|
-
stepAll: (timestamp) => {
|
|
1259
|
-
getScheduler().step(timestamp);
|
|
1260
|
-
},
|
|
1261
|
-
/**
|
|
1262
|
-
* Pause this job (set enabled=false).
|
|
1263
|
-
* Job remains registered but won't run.
|
|
1264
|
-
*/
|
|
1265
|
-
pause: () => {
|
|
1266
|
-
getScheduler().pauseJob(id);
|
|
1267
|
-
},
|
|
1268
|
-
/**
|
|
1269
|
-
* Resume this job (set enabled=true).
|
|
1270
|
-
*/
|
|
1271
|
-
resume: () => {
|
|
1272
|
-
getScheduler().resumeJob(id);
|
|
1273
|
-
},
|
|
1274
|
-
/**
|
|
1275
|
-
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1276
|
-
* No need for forceUpdate() in your components.
|
|
1277
|
-
*/
|
|
1278
|
-
isPaused
|
|
1279
|
-
};
|
|
1280
|
-
}, [id, isPaused]);
|
|
1281
|
-
return controls;
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1285
|
-
function getUrls(input) {
|
|
1286
|
-
if (typeof input === "string") return [input];
|
|
1287
|
-
if (Array.isArray(input)) return input;
|
|
1288
|
-
return Object.values(input);
|
|
1289
|
-
}
|
|
1290
|
-
function allUrlsCached(urls, textureCache) {
|
|
1291
|
-
return urls.every((url) => textureCache.has(url));
|
|
1292
|
-
}
|
|
1293
|
-
function buildFromCache(input, textureCache) {
|
|
1294
|
-
if (typeof input === "string") {
|
|
1295
|
-
return textureCache.get(input);
|
|
1296
|
-
} else if (Array.isArray(input)) {
|
|
1297
|
-
return input.map((url) => textureCache.get(url));
|
|
1298
|
-
} else {
|
|
1299
|
-
const result = {};
|
|
1300
|
-
const objInput = input;
|
|
1301
|
-
for (const key in objInput) {
|
|
1302
|
-
result[key] = textureCache.get(objInput[key]);
|
|
1303
|
-
}
|
|
1304
|
-
return result;
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
function useTexture(input, optionsOrOnLoad) {
|
|
1308
|
-
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1309
|
-
const store = useStore();
|
|
1310
|
-
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1311
|
-
const { onLoad, cache = true } = options;
|
|
1312
|
-
const onLoadRef = useRef(onLoad);
|
|
1313
|
-
onLoadRef.current = onLoad;
|
|
1314
|
-
const onLoadCalledForRef = useRef(null);
|
|
1315
|
-
const urls = useMemo(() => getUrls(input), [input]);
|
|
1316
|
-
const cachedResult = useMemo(() => {
|
|
1317
|
-
if (!cache) return null;
|
|
1318
|
-
const textures = store.getState().textures;
|
|
1319
|
-
if (!allUrlsCached(urls, textures)) return null;
|
|
1320
|
-
return buildFromCache(input, textures);
|
|
1321
|
-
}, [cache, urls, input, store]);
|
|
1322
|
-
const loadedTextures = useLoader(
|
|
1323
|
-
TextureLoader,
|
|
1324
|
-
IsObject(input) ? Object.values(input) : input
|
|
1325
|
-
);
|
|
1326
|
-
const inputKey = urls.join("\0");
|
|
1327
|
-
useLayoutEffect(() => {
|
|
1328
|
-
if (cachedResult) return;
|
|
1329
|
-
if (onLoadCalledForRef.current === inputKey) return;
|
|
1330
|
-
onLoadCalledForRef.current = inputKey;
|
|
1331
|
-
onLoadRef.current?.(loadedTextures);
|
|
1332
|
-
}, [cachedResult, loadedTextures, inputKey]);
|
|
1333
|
-
useEffect(() => {
|
|
1334
|
-
if (cachedResult) return;
|
|
1335
|
-
if ("initTexture" in renderer) {
|
|
1336
|
-
let textureArray = [];
|
|
1337
|
-
if (Array.isArray(loadedTextures)) {
|
|
1338
|
-
textureArray = loadedTextures;
|
|
1339
|
-
} else if (loadedTextures instanceof Texture$1) {
|
|
1340
|
-
textureArray = [loadedTextures];
|
|
1341
|
-
} else if (IsObject(loadedTextures)) {
|
|
1342
|
-
textureArray = Object.values(loadedTextures);
|
|
1343
|
-
}
|
|
1344
|
-
textureArray.forEach((texture) => {
|
|
1345
|
-
if (texture instanceof Texture$1) {
|
|
1346
|
-
renderer.initTexture(texture);
|
|
1347
|
-
}
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
}, [renderer, loadedTextures, cachedResult]);
|
|
1351
|
-
const mappedTextures = useMemo(() => {
|
|
1352
|
-
if (cachedResult) return cachedResult;
|
|
1353
|
-
if (IsObject(input)) {
|
|
1354
|
-
const keyed = {};
|
|
1355
|
-
const textureArray = loadedTextures;
|
|
1356
|
-
let i = 0;
|
|
1357
|
-
for (const key in input) keyed[key] = textureArray[i++];
|
|
1358
|
-
return keyed;
|
|
1359
|
-
} else {
|
|
1360
|
-
return loadedTextures;
|
|
1361
|
-
}
|
|
1362
|
-
}, [input, loadedTextures, cachedResult]);
|
|
1363
|
-
useEffect(() => {
|
|
1364
|
-
if (!cache) return;
|
|
1365
|
-
const urlTextureMap = [];
|
|
1366
|
-
if (typeof input === "string") {
|
|
1367
|
-
urlTextureMap.push([input, mappedTextures]);
|
|
1368
|
-
} else if (Array.isArray(input)) {
|
|
1369
|
-
const textureArray = mappedTextures;
|
|
1370
|
-
input.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1371
|
-
} else if (IsObject(input)) {
|
|
1372
|
-
const textureRecord = mappedTextures;
|
|
1373
|
-
for (const key in input) {
|
|
1374
|
-
const url = input[key];
|
|
1375
|
-
urlTextureMap.push([url, textureRecord[key]]);
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
store.setState((state) => {
|
|
1379
|
-
const refs = new Map(state._textureRefs);
|
|
1380
|
-
let textures = state.textures;
|
|
1381
|
-
let added = false;
|
|
1382
|
-
for (const [url, texture] of urlTextureMap) {
|
|
1383
|
-
if (!textures.has(url)) {
|
|
1384
|
-
if (!added) {
|
|
1385
|
-
textures = new Map(textures);
|
|
1386
|
-
added = true;
|
|
1387
|
-
}
|
|
1388
|
-
textures.set(url, texture);
|
|
1389
|
-
}
|
|
1390
|
-
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
1391
|
-
}
|
|
1392
|
-
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
1393
|
-
});
|
|
1394
|
-
return () => store.setState((state) => {
|
|
1395
|
-
const refs = new Map(state._textureRefs);
|
|
1396
|
-
for (const [url] of urlTextureMap) {
|
|
1397
|
-
const next = (refs.get(url) ?? 0) - 1;
|
|
1398
|
-
if (next <= 0) refs.delete(url);
|
|
1399
|
-
else refs.set(url, next);
|
|
1400
|
-
}
|
|
1401
|
-
return { _textureRefs: refs };
|
|
1402
|
-
});
|
|
1403
|
-
}, [cache, input, mappedTextures, store]);
|
|
1404
|
-
return mappedTextures;
|
|
1405
|
-
}
|
|
1406
|
-
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
1407
|
-
useTexture.clear = (input) => useLoader.clear(TextureLoader, input);
|
|
1408
|
-
const Texture = ({
|
|
1409
|
-
children,
|
|
1410
|
-
input,
|
|
1411
|
-
onLoad,
|
|
1412
|
-
cache
|
|
1413
|
-
}) => {
|
|
1414
|
-
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1415
|
-
const ret = useTexture(input, options);
|
|
1416
|
-
return /* @__PURE__ */ jsx(Fragment, { children: children?.(ret) });
|
|
1163
|
+
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
1164
|
+
useTexture.clear = (input) => useLoader.clear(TextureLoader, input);
|
|
1165
|
+
const Texture = ({
|
|
1166
|
+
children,
|
|
1167
|
+
input,
|
|
1168
|
+
onLoad,
|
|
1169
|
+
cache
|
|
1170
|
+
}) => {
|
|
1171
|
+
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1172
|
+
const ret = useTexture(input, options);
|
|
1173
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children?.(ret) });
|
|
1417
1174
|
};
|
|
1418
1175
|
|
|
1419
1176
|
function useTextures(selector) {
|
|
@@ -1471,13 +1228,13 @@ function useTextures(selector) {
|
|
|
1471
1228
|
};
|
|
1472
1229
|
}, [store]);
|
|
1473
1230
|
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
1474
|
-
const selected = useThree(subscribe);
|
|
1231
|
+
const selected = useThree$1(subscribe);
|
|
1475
1232
|
return selector ? selected : registry;
|
|
1476
1233
|
}
|
|
1477
1234
|
|
|
1478
1235
|
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
1479
|
-
const isLegacy = useThree((s) => s.isLegacy);
|
|
1480
|
-
const size = useThree((s) => s.size);
|
|
1236
|
+
const isLegacy = useThree$1((s) => s.isLegacy);
|
|
1237
|
+
const size = useThree$1((s) => s.size);
|
|
1481
1238
|
let width;
|
|
1482
1239
|
let height;
|
|
1483
1240
|
let opts;
|
|
@@ -1534,7 +1291,7 @@ function useEnvironment({
|
|
|
1534
1291
|
const { extension, isCubemap } = getExtension(files);
|
|
1535
1292
|
const loader = getLoader(extension);
|
|
1536
1293
|
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1537
|
-
const renderer = useThree((state) => state.renderer);
|
|
1294
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
1538
1295
|
useLayoutEffect(() => {
|
|
1539
1296
|
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
1540
1297
|
function clearGainmapTexture() {
|
|
@@ -1561,7 +1318,7 @@ function useEnvironment({
|
|
|
1561
1318
|
texture = texture.renderTarget?.texture;
|
|
1562
1319
|
}
|
|
1563
1320
|
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
1564
|
-
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
1321
|
+
texture.colorSpace = colorSpace ?? (isCubemap && extension !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
1565
1322
|
return texture;
|
|
1566
1323
|
}
|
|
1567
1324
|
const preloadDefaultOptions = {
|
|
@@ -1614,22 +1371,15 @@ function getExtension(files) {
|
|
|
1614
1371
|
const isCubemap = isArray(files) && files.length === 6;
|
|
1615
1372
|
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
1616
1373
|
const firstEntry = isArray(files) ? files[0] : files;
|
|
1617
|
-
const
|
|
1374
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1375
|
+
const extension = isCubemap ? firstExtension === "hdr" ? "hdr-cube" : "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstExtension;
|
|
1618
1376
|
return { extension, isCubemap, isGainmap };
|
|
1619
1377
|
}
|
|
1620
1378
|
function getLoader(extension) {
|
|
1621
|
-
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
1379
|
+
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr-cube" ? HDRCubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
1622
1380
|
return loader;
|
|
1623
1381
|
}
|
|
1624
1382
|
|
|
1625
|
-
function useStore() {
|
|
1626
|
-
const store = useContext(context);
|
|
1627
|
-
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1628
|
-
return store;
|
|
1629
|
-
}
|
|
1630
|
-
function useThree(selector = (state) => state, equalityFn) {
|
|
1631
|
-
return useStore()(selector, equalityFn);
|
|
1632
|
-
}
|
|
1633
1383
|
function useInstanceHandle(ref) {
|
|
1634
1384
|
const instance = useRef(null);
|
|
1635
1385
|
useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
@@ -1669,13 +1419,19 @@ function addTail(callback) {
|
|
|
1669
1419
|
return getScheduler().onIdle(callback);
|
|
1670
1420
|
}
|
|
1671
1421
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1672
|
-
|
|
1422
|
+
const rootId = state?.internal?.rootId;
|
|
1423
|
+
const scheduler = getScheduler();
|
|
1424
|
+
if (rootId) scheduler.invalidateRoot(rootId, frames, stackFrames);
|
|
1425
|
+
else scheduler.invalidate(frames, stackFrames);
|
|
1673
1426
|
}
|
|
1674
|
-
function advance(timestamp) {
|
|
1675
|
-
|
|
1427
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1428
|
+
const rootId = state?.internal?.rootId;
|
|
1429
|
+
const scheduler = getScheduler();
|
|
1430
|
+
if (rootId) scheduler.stepRoot(rootId, timestamp);
|
|
1431
|
+
else scheduler.step(timestamp);
|
|
1676
1432
|
}
|
|
1677
1433
|
|
|
1678
|
-
const version = "10.0.0-alpha.
|
|
1434
|
+
const version = "10.0.0-alpha.5";
|
|
1679
1435
|
const packageData = {
|
|
1680
1436
|
version: version};
|
|
1681
1437
|
|
|
@@ -13534,7 +13290,10 @@ function extend(objects) {
|
|
|
13534
13290
|
catalogue[Component] = objects;
|
|
13535
13291
|
return Component;
|
|
13536
13292
|
} else {
|
|
13537
|
-
|
|
13293
|
+
for (const name in objects) {
|
|
13294
|
+
const object = objects[name];
|
|
13295
|
+
if (isConstructor(object)) catalogue[name] = object;
|
|
13296
|
+
}
|
|
13538
13297
|
}
|
|
13539
13298
|
}
|
|
13540
13299
|
function validateInstance(type, props) {
|
|
@@ -13882,7 +13641,7 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13882
13641
|
getRootHostContext: () => NO_CONTEXT,
|
|
13883
13642
|
getChildHostContext: () => NO_CONTEXT,
|
|
13884
13643
|
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
13885
|
-
validateInstance(type, newProps);
|
|
13644
|
+
validateInstance(instance.type, newProps);
|
|
13886
13645
|
let reconstruct = false;
|
|
13887
13646
|
if (instance.type === "primitive" && oldProps.object !== newProps.object) reconstruct = true;
|
|
13888
13647
|
else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
|
|
@@ -13897,162 +13656,491 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13897
13656
|
else delete instance.props.attach;
|
|
13898
13657
|
if (Object.keys(changedProps).length) applyProps(instance.object, changedProps);
|
|
13899
13658
|
}
|
|
13900
|
-
},
|
|
13901
|
-
finalizeInitialChildren: (instance) => {
|
|
13902
|
-
for (const prop in instance.props) {
|
|
13903
|
-
if (isFromRef(instance.props[prop])) return true;
|
|
13659
|
+
},
|
|
13660
|
+
finalizeInitialChildren: (instance) => {
|
|
13661
|
+
for (const prop in instance.props) {
|
|
13662
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
13663
|
+
}
|
|
13664
|
+
return false;
|
|
13665
|
+
},
|
|
13666
|
+
commitMount(instance) {
|
|
13667
|
+
const resolved = {};
|
|
13668
|
+
for (const prop in instance.props) {
|
|
13669
|
+
const value = instance.props[prop];
|
|
13670
|
+
if (isFromRef(value)) {
|
|
13671
|
+
const { [FROM_REF]: ref, transform } = value;
|
|
13672
|
+
if (ref.current != null) resolved[prop] = transform ? transform(ref.current) : ref.current;
|
|
13673
|
+
}
|
|
13674
|
+
}
|
|
13675
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
13676
|
+
},
|
|
13677
|
+
getPublicInstance: (instance) => instance?.object,
|
|
13678
|
+
prepareForCommit: () => null,
|
|
13679
|
+
preparePortalMount: (container) => {
|
|
13680
|
+
const target = container.getState().internal.container ?? container.getState().scene;
|
|
13681
|
+
return prepare(target, container, "", {});
|
|
13682
|
+
},
|
|
13683
|
+
// Reconstructed instances are swapped once all mutations are committed,
|
|
13684
|
+
// before layout effects run so refs point to the new objects
|
|
13685
|
+
resetAfterCommit: flushReconstructedInstances,
|
|
13686
|
+
shouldSetTextContent: () => false,
|
|
13687
|
+
clearContainer: () => false,
|
|
13688
|
+
hideInstance,
|
|
13689
|
+
unhideInstance,
|
|
13690
|
+
createTextInstance: handleTextInstance,
|
|
13691
|
+
hideTextInstance: handleTextInstance,
|
|
13692
|
+
unhideTextInstance: handleTextInstance,
|
|
13693
|
+
// Mirrors react-dom, which flushes discrete work in microtasks
|
|
13694
|
+
supportsMicrotasks: true,
|
|
13695
|
+
scheduleMicrotask,
|
|
13696
|
+
scheduleTimeout: typeof setTimeout === "function" ? setTimeout : void 0,
|
|
13697
|
+
cancelTimeout: typeof clearTimeout === "function" ? clearTimeout : void 0,
|
|
13698
|
+
noTimeout: -1,
|
|
13699
|
+
getInstanceFromNode: () => null,
|
|
13700
|
+
beforeActiveInstanceBlur() {
|
|
13701
|
+
},
|
|
13702
|
+
afterActiveInstanceBlur() {
|
|
13703
|
+
},
|
|
13704
|
+
detachDeletedInstance() {
|
|
13705
|
+
},
|
|
13706
|
+
prepareScopeUpdate() {
|
|
13707
|
+
},
|
|
13708
|
+
getInstanceFromScope: () => null,
|
|
13709
|
+
shouldAttemptEagerTransition: () => false,
|
|
13710
|
+
trackSchedulerEvent: () => {
|
|
13711
|
+
},
|
|
13712
|
+
resolveEventType: () => null,
|
|
13713
|
+
resolveEventTimeStamp: () => -1.1,
|
|
13714
|
+
requestPostPaintCallback() {
|
|
13715
|
+
},
|
|
13716
|
+
maySuspendCommit: () => false,
|
|
13717
|
+
preloadInstance: () => true,
|
|
13718
|
+
// true indicates already loaded
|
|
13719
|
+
suspendInstance() {
|
|
13720
|
+
},
|
|
13721
|
+
waitForCommitToBeReady: () => null,
|
|
13722
|
+
NotPendingTransition: null,
|
|
13723
|
+
// The reconciler types use the internal ReactContext with all the hidden properties
|
|
13724
|
+
// so we have to cast from the public React.Context type
|
|
13725
|
+
HostTransitionContext: /* @__PURE__ */ React.createContext(
|
|
13726
|
+
null
|
|
13727
|
+
),
|
|
13728
|
+
setCurrentUpdatePriority(newPriority) {
|
|
13729
|
+
currentUpdatePriority = newPriority;
|
|
13730
|
+
},
|
|
13731
|
+
getCurrentUpdatePriority() {
|
|
13732
|
+
return currentUpdatePriority;
|
|
13733
|
+
},
|
|
13734
|
+
resolveUpdatePriority() {
|
|
13735
|
+
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13736
|
+
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13737
|
+
if (eventType === void 0) return r;
|
|
13738
|
+
return getEventPriority(eventType);
|
|
13739
|
+
},
|
|
13740
|
+
resetFormInstance() {
|
|
13741
|
+
},
|
|
13742
|
+
// @ts-ignore DefinitelyTyped is not up to date
|
|
13743
|
+
rendererPackageName: "@react-three/fiber",
|
|
13744
|
+
rendererVersion: packageData.version,
|
|
13745
|
+
// 19.2 Reconciler
|
|
13746
|
+
// https://github.com/facebook/react/pull/31975
|
|
13747
|
+
// https://github.com/facebook/react/pull/31999
|
|
13748
|
+
applyViewTransitionName(_instance, _name, _className) {
|
|
13749
|
+
},
|
|
13750
|
+
restoreViewTransitionName(_instance, _props) {
|
|
13751
|
+
},
|
|
13752
|
+
cancelViewTransitionName(_instance, _name, _props) {
|
|
13753
|
+
},
|
|
13754
|
+
cancelRootViewTransitionName(_rootContainer) {
|
|
13755
|
+
},
|
|
13756
|
+
restoreRootViewTransitionName(_rootContainer) {
|
|
13757
|
+
},
|
|
13758
|
+
InstanceMeasurement: null,
|
|
13759
|
+
measureInstance: (_instance) => null,
|
|
13760
|
+
wasInstanceInViewport: (_measurement) => true,
|
|
13761
|
+
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
13762
|
+
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
13763
|
+
// https://github.com/facebook/react/pull/32002
|
|
13764
|
+
// https://github.com/facebook/react/pull/34486
|
|
13765
|
+
suspendOnActiveViewTransition(_state, _container) {
|
|
13766
|
+
},
|
|
13767
|
+
// https://github.com/facebook/react/pull/32451
|
|
13768
|
+
// https://github.com/facebook/react/pull/32760
|
|
13769
|
+
startGestureTransition: () => null,
|
|
13770
|
+
startViewTransition: () => null,
|
|
13771
|
+
stopViewTransition(_transition) {
|
|
13772
|
+
},
|
|
13773
|
+
// https://github.com/facebook/react/pull/32038
|
|
13774
|
+
createViewTransitionInstance: (_name) => null,
|
|
13775
|
+
// https://github.com/facebook/react/pull/32379
|
|
13776
|
+
// https://github.com/facebook/react/pull/32786
|
|
13777
|
+
getCurrentGestureOffset(_provider) {
|
|
13778
|
+
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
13779
|
+
},
|
|
13780
|
+
// https://github.com/facebook/react/pull/32500
|
|
13781
|
+
cloneMutableInstance(instance, _keepChildren) {
|
|
13782
|
+
return instance;
|
|
13783
|
+
},
|
|
13784
|
+
cloneMutableTextInstance(textInstance) {
|
|
13785
|
+
return textInstance;
|
|
13786
|
+
},
|
|
13787
|
+
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
13788
|
+
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
13789
|
+
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
13790
|
+
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
13791
|
+
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
13792
|
+
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
13793
|
+
cloneRootViewTransitionContainer(_rootContainer) {
|
|
13794
|
+
},
|
|
13795
|
+
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
13796
|
+
},
|
|
13797
|
+
// https://github.com/facebook/react/pull/32465
|
|
13798
|
+
createFragmentInstance: (_fiber) => null,
|
|
13799
|
+
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
13800
|
+
},
|
|
13801
|
+
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
13802
|
+
},
|
|
13803
|
+
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
13804
|
+
},
|
|
13805
|
+
// https://github.com/facebook/react/pull/32653
|
|
13806
|
+
measureClonedInstance: (_instance) => null,
|
|
13807
|
+
// https://github.com/facebook/react/pull/32819
|
|
13808
|
+
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
13809
|
+
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
13810
|
+
// https://github.com/facebook/react/pull/34486
|
|
13811
|
+
startSuspendingCommit: () => null,
|
|
13812
|
+
// https://github.com/facebook/react/pull/34522
|
|
13813
|
+
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
13814
|
+
});
|
|
13815
|
+
|
|
13816
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
13817
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
13818
|
+
if (!stack) return false;
|
|
13819
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
13820
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
13821
|
+
}
|
|
13822
|
+
|
|
13823
|
+
const createStore = (invalidate, advance) => {
|
|
13824
|
+
const rootStore = createWithEqualityFn((set, get) => {
|
|
13825
|
+
const position = new Vector3();
|
|
13826
|
+
const defaultTarget = new Vector3();
|
|
13827
|
+
const tempTarget = new Vector3();
|
|
13828
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
13829
|
+
const { width, height, top, left } = size;
|
|
13830
|
+
const aspect = width / height;
|
|
13831
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
13832
|
+
else tempTarget.set(...target);
|
|
13833
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
13834
|
+
if (isOrthographicCamera(camera)) {
|
|
13835
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
13836
|
+
} else {
|
|
13837
|
+
const fov = camera.fov * Math.PI / 180;
|
|
13838
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
13839
|
+
const w = h * (width / height);
|
|
13840
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
13841
|
+
}
|
|
13842
|
+
}
|
|
13843
|
+
let performanceTimeout = void 0;
|
|
13844
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
13845
|
+
const pointer = new Vector2();
|
|
13846
|
+
const rootState = {
|
|
13847
|
+
set,
|
|
13848
|
+
get,
|
|
13849
|
+
// Mock objects that have to be configured
|
|
13850
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
13851
|
+
primaryStore: null,
|
|
13852
|
+
gl: null,
|
|
13853
|
+
renderer: null,
|
|
13854
|
+
camera: null,
|
|
13855
|
+
frustum: new Frustum(),
|
|
13856
|
+
autoUpdateFrustum: true,
|
|
13857
|
+
raycaster: null,
|
|
13858
|
+
events: {
|
|
13859
|
+
priority: 1,
|
|
13860
|
+
enabled: true,
|
|
13861
|
+
connected: false,
|
|
13862
|
+
frameTimedRaycasts: true,
|
|
13863
|
+
alwaysFireOnScroll: true,
|
|
13864
|
+
updateOnFrame: false
|
|
13865
|
+
},
|
|
13866
|
+
scene: null,
|
|
13867
|
+
rootScene: null,
|
|
13868
|
+
xr: null,
|
|
13869
|
+
inspector: null,
|
|
13870
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
13871
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
13872
|
+
textureColorSpace: SRGBColorSpace,
|
|
13873
|
+
isLegacy: false,
|
|
13874
|
+
webGPUSupported: false,
|
|
13875
|
+
isNative: false,
|
|
13876
|
+
controls: null,
|
|
13877
|
+
pointer,
|
|
13878
|
+
mouse: pointer,
|
|
13879
|
+
frameloop: "always",
|
|
13880
|
+
onPointerMissed: void 0,
|
|
13881
|
+
onDragOverMissed: void 0,
|
|
13882
|
+
onDropMissed: void 0,
|
|
13883
|
+
performance: {
|
|
13884
|
+
current: 1,
|
|
13885
|
+
min: 0.5,
|
|
13886
|
+
max: 1,
|
|
13887
|
+
debounce: 200,
|
|
13888
|
+
regress: () => {
|
|
13889
|
+
const state2 = get();
|
|
13890
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
13891
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
13892
|
+
performanceTimeout = setTimeout(
|
|
13893
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
13894
|
+
state2.performance.debounce
|
|
13895
|
+
);
|
|
13896
|
+
}
|
|
13897
|
+
},
|
|
13898
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
13899
|
+
viewport: {
|
|
13900
|
+
initialDpr: 0,
|
|
13901
|
+
dpr: 0,
|
|
13902
|
+
width: 0,
|
|
13903
|
+
height: 0,
|
|
13904
|
+
top: 0,
|
|
13905
|
+
left: 0,
|
|
13906
|
+
aspect: 0,
|
|
13907
|
+
distance: 0,
|
|
13908
|
+
factor: 0,
|
|
13909
|
+
getCurrentViewport
|
|
13910
|
+
},
|
|
13911
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
13912
|
+
setSize: (width, height, top, left) => {
|
|
13913
|
+
const state2 = get();
|
|
13914
|
+
if (width === void 0) {
|
|
13915
|
+
set({ _sizeImperative: false });
|
|
13916
|
+
if (state2._sizeProps) {
|
|
13917
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
13918
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
13919
|
+
const currentSize = state2.size;
|
|
13920
|
+
const newSize = {
|
|
13921
|
+
width: propW ?? currentSize.width,
|
|
13922
|
+
height: propH ?? currentSize.height,
|
|
13923
|
+
top: currentSize.top,
|
|
13924
|
+
left: currentSize.left
|
|
13925
|
+
};
|
|
13926
|
+
set((s) => ({
|
|
13927
|
+
size: newSize,
|
|
13928
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
13929
|
+
}));
|
|
13930
|
+
get().invalidate();
|
|
13931
|
+
}
|
|
13932
|
+
}
|
|
13933
|
+
return;
|
|
13934
|
+
}
|
|
13935
|
+
const w = width;
|
|
13936
|
+
const h = height ?? width;
|
|
13937
|
+
const t = top ?? state2.size.top;
|
|
13938
|
+
const l = left ?? state2.size.left;
|
|
13939
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
13940
|
+
set((s) => ({
|
|
13941
|
+
size,
|
|
13942
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
13943
|
+
_sizeImperative: true
|
|
13944
|
+
}));
|
|
13945
|
+
get().invalidate();
|
|
13946
|
+
},
|
|
13947
|
+
setDpr: (dpr) => set((state2) => {
|
|
13948
|
+
const resolved = calculateDpr(dpr);
|
|
13949
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
13950
|
+
}),
|
|
13951
|
+
setFrameloop: (frameloop = "always") => {
|
|
13952
|
+
const rootId = get().internal.rootId;
|
|
13953
|
+
if (rootId) getScheduler().setRootFrameloop(rootId, frameloop);
|
|
13954
|
+
set(() => ({ frameloop }));
|
|
13955
|
+
},
|
|
13956
|
+
setError: (error) => set(() => ({ error })),
|
|
13957
|
+
error: null,
|
|
13958
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
13959
|
+
uniforms: {},
|
|
13960
|
+
nodes: {},
|
|
13961
|
+
buffers: {},
|
|
13962
|
+
gpuStorage: {},
|
|
13963
|
+
textures: /* @__PURE__ */ new Map(),
|
|
13964
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
13965
|
+
renderPipeline: null,
|
|
13966
|
+
passes: {},
|
|
13967
|
+
_hmrVersion: 0,
|
|
13968
|
+
_sizeImperative: false,
|
|
13969
|
+
_sizeProps: null,
|
|
13970
|
+
previousRoot: void 0,
|
|
13971
|
+
internal: {
|
|
13972
|
+
// Events
|
|
13973
|
+
interaction: [],
|
|
13974
|
+
subscribers: [],
|
|
13975
|
+
// Per-pointer state (new unified structure)
|
|
13976
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
13977
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
13978
|
+
lastEvent: React.createRef(),
|
|
13979
|
+
// Deprecated but kept for backwards compatibility
|
|
13980
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
13981
|
+
initialClick: [0, 0],
|
|
13982
|
+
initialHits: [],
|
|
13983
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
13984
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
13985
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
13986
|
+
// Occlusion system (WebGPU only)
|
|
13987
|
+
occlusionEnabled: false,
|
|
13988
|
+
occlusionObserver: null,
|
|
13989
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
13990
|
+
helperGroup: null,
|
|
13991
|
+
// Updates
|
|
13992
|
+
active: false,
|
|
13993
|
+
frames: 0,
|
|
13994
|
+
priority: 0,
|
|
13995
|
+
subscribe: (ref, priority, store) => {
|
|
13996
|
+
const internal = get().internal;
|
|
13997
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
13998
|
+
internal.subscribers.push({ ref, priority, store });
|
|
13999
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14000
|
+
return () => {
|
|
14001
|
+
const internal2 = get().internal;
|
|
14002
|
+
if (internal2?.subscribers) {
|
|
14003
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14004
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14005
|
+
}
|
|
14006
|
+
};
|
|
14007
|
+
},
|
|
14008
|
+
// Renderer Storage (single source of truth)
|
|
14009
|
+
actualRenderer: null,
|
|
14010
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14011
|
+
scheduler: null,
|
|
14012
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
14013
|
+
renderOverride: null
|
|
14014
|
+
}
|
|
14015
|
+
};
|
|
14016
|
+
return rootState;
|
|
14017
|
+
});
|
|
14018
|
+
const state = rootStore.getState();
|
|
14019
|
+
Object.defineProperty(state, "gl", {
|
|
14020
|
+
get() {
|
|
14021
|
+
const currentState = rootStore.getState();
|
|
14022
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14023
|
+
const stack = new Error().stack || "";
|
|
14024
|
+
if (!isInternalRendererAccess(stack)) {
|
|
14025
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14026
|
+
notifyDepreciated({
|
|
14027
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
14028
|
+
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
|
|
14029
|
+
});
|
|
14030
|
+
}
|
|
14031
|
+
}
|
|
14032
|
+
return currentState.internal.actualRenderer;
|
|
14033
|
+
},
|
|
14034
|
+
set(value) {
|
|
14035
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14036
|
+
},
|
|
14037
|
+
enumerable: true,
|
|
14038
|
+
configurable: true
|
|
14039
|
+
});
|
|
14040
|
+
Object.defineProperty(state, "renderer", {
|
|
14041
|
+
get() {
|
|
14042
|
+
return rootStore.getState().internal.actualRenderer;
|
|
14043
|
+
},
|
|
14044
|
+
set(value) {
|
|
14045
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14046
|
+
},
|
|
14047
|
+
enumerable: true,
|
|
14048
|
+
configurable: true
|
|
14049
|
+
});
|
|
14050
|
+
let oldScene = state.scene;
|
|
14051
|
+
rootStore.subscribe(() => {
|
|
14052
|
+
const currentState = rootStore.getState();
|
|
14053
|
+
const { scene, rootScene, set } = currentState;
|
|
14054
|
+
if (scene !== oldScene) {
|
|
14055
|
+
oldScene = scene;
|
|
14056
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
14057
|
+
set({ rootScene: scene });
|
|
14058
|
+
}
|
|
14059
|
+
}
|
|
14060
|
+
});
|
|
14061
|
+
let oldSize = state.size;
|
|
14062
|
+
let oldDpr = state.viewport.dpr;
|
|
14063
|
+
let oldCamera = state.camera;
|
|
14064
|
+
rootStore.subscribe(() => {
|
|
14065
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14066
|
+
const actualRenderer = internal.actualRenderer;
|
|
14067
|
+
const canvasTarget = internal.canvasTarget;
|
|
14068
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14069
|
+
oldSize = size;
|
|
14070
|
+
oldDpr = viewport.dpr;
|
|
14071
|
+
updateCamera(camera, size);
|
|
14072
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14073
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14074
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
14075
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14076
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
13904
14077
|
}
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
14078
|
+
if (camera !== oldCamera) {
|
|
14079
|
+
oldCamera = camera;
|
|
14080
|
+
const { rootScene } = rootStore.getState();
|
|
14081
|
+
if (camera && rootScene && !camera.parent) {
|
|
14082
|
+
rootScene.add(camera);
|
|
14083
|
+
}
|
|
14084
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14085
|
+
const currentState = rootStore.getState();
|
|
14086
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
14087
|
+
updateFrustum(camera, currentState.frustum);
|
|
13914
14088
|
}
|
|
13915
14089
|
}
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
),
|
|
13969
|
-
|
|
13970
|
-
currentUpdatePriority = newPriority;
|
|
13971
|
-
},
|
|
13972
|
-
getCurrentUpdatePriority() {
|
|
13973
|
-
return currentUpdatePriority;
|
|
13974
|
-
},
|
|
13975
|
-
resolveUpdatePriority() {
|
|
13976
|
-
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13977
|
-
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13978
|
-
if (eventType === void 0) return r;
|
|
13979
|
-
return getEventPriority(eventType);
|
|
13980
|
-
},
|
|
13981
|
-
resetFormInstance() {
|
|
13982
|
-
},
|
|
13983
|
-
// @ts-ignore DefinitelyTyped is not up to date
|
|
13984
|
-
rendererPackageName: "@react-three/fiber",
|
|
13985
|
-
rendererVersion: packageData.version,
|
|
13986
|
-
// 19.2 Reconciler
|
|
13987
|
-
// https://github.com/facebook/react/pull/31975
|
|
13988
|
-
// https://github.com/facebook/react/pull/31999
|
|
13989
|
-
applyViewTransitionName(_instance, _name, _className) {
|
|
13990
|
-
},
|
|
13991
|
-
restoreViewTransitionName(_instance, _props) {
|
|
13992
|
-
},
|
|
13993
|
-
cancelViewTransitionName(_instance, _name, _props) {
|
|
13994
|
-
},
|
|
13995
|
-
cancelRootViewTransitionName(_rootContainer) {
|
|
13996
|
-
},
|
|
13997
|
-
restoreRootViewTransitionName(_rootContainer) {
|
|
13998
|
-
},
|
|
13999
|
-
InstanceMeasurement: null,
|
|
14000
|
-
measureInstance: (_instance) => null,
|
|
14001
|
-
wasInstanceInViewport: (_measurement) => true,
|
|
14002
|
-
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
14003
|
-
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
14004
|
-
// https://github.com/facebook/react/pull/32002
|
|
14005
|
-
// https://github.com/facebook/react/pull/34486
|
|
14006
|
-
suspendOnActiveViewTransition(_state, _container) {
|
|
14007
|
-
},
|
|
14008
|
-
// https://github.com/facebook/react/pull/32451
|
|
14009
|
-
// https://github.com/facebook/react/pull/32760
|
|
14010
|
-
startGestureTransition: () => null,
|
|
14011
|
-
startViewTransition: () => null,
|
|
14012
|
-
stopViewTransition(_transition) {
|
|
14013
|
-
},
|
|
14014
|
-
// https://github.com/facebook/react/pull/32038
|
|
14015
|
-
createViewTransitionInstance: (_name) => null,
|
|
14016
|
-
// https://github.com/facebook/react/pull/32379
|
|
14017
|
-
// https://github.com/facebook/react/pull/32786
|
|
14018
|
-
getCurrentGestureOffset(_provider) {
|
|
14019
|
-
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
14020
|
-
},
|
|
14021
|
-
// https://github.com/facebook/react/pull/32500
|
|
14022
|
-
cloneMutableInstance(instance, _keepChildren) {
|
|
14023
|
-
return instance;
|
|
14024
|
-
},
|
|
14025
|
-
cloneMutableTextInstance(textInstance) {
|
|
14026
|
-
return textInstance;
|
|
14027
|
-
},
|
|
14028
|
-
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
14029
|
-
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
14030
|
-
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
14031
|
-
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
14032
|
-
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
14033
|
-
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
14034
|
-
cloneRootViewTransitionContainer(_rootContainer) {
|
|
14035
|
-
},
|
|
14036
|
-
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
14037
|
-
},
|
|
14038
|
-
// https://github.com/facebook/react/pull/32465
|
|
14039
|
-
createFragmentInstance: (_fiber) => null,
|
|
14040
|
-
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
14041
|
-
},
|
|
14042
|
-
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
14043
|
-
},
|
|
14044
|
-
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
14045
|
-
},
|
|
14046
|
-
// https://github.com/facebook/react/pull/32653
|
|
14047
|
-
measureClonedInstance: (_instance) => null,
|
|
14048
|
-
// https://github.com/facebook/react/pull/32819
|
|
14049
|
-
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
14050
|
-
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
14051
|
-
// https://github.com/facebook/react/pull/34486
|
|
14052
|
-
startSuspendingCommit: () => null,
|
|
14053
|
-
// https://github.com/facebook/react/pull/34522
|
|
14054
|
-
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14055
|
-
});
|
|
14090
|
+
});
|
|
14091
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
14092
|
+
return rootStore;
|
|
14093
|
+
};
|
|
14094
|
+
|
|
14095
|
+
const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
|
|
14096
|
+
function getRegistry() {
|
|
14097
|
+
return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
|
|
14098
|
+
extensions: /* @__PURE__ */ new Map(),
|
|
14099
|
+
roots: /* @__PURE__ */ new Set(),
|
|
14100
|
+
applied: /* @__PURE__ */ new WeakMap()
|
|
14101
|
+
});
|
|
14102
|
+
}
|
|
14103
|
+
function setupRoot(registry, store, extension) {
|
|
14104
|
+
let applied = registry.applied.get(store);
|
|
14105
|
+
if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
|
|
14106
|
+
if (applied.has(extension.name)) return;
|
|
14107
|
+
applied.set(extension.name, extension);
|
|
14108
|
+
const patch = extension.setup?.(store);
|
|
14109
|
+
if (patch) store.setState(patch);
|
|
14110
|
+
}
|
|
14111
|
+
function registerRootExtension(extension) {
|
|
14112
|
+
const registry = getRegistry();
|
|
14113
|
+
registry.extensions.set(extension.name, extension);
|
|
14114
|
+
for (const store of registry.roots) setupRoot(registry, store, extension);
|
|
14115
|
+
return () => {
|
|
14116
|
+
if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
|
|
14117
|
+
};
|
|
14118
|
+
}
|
|
14119
|
+
function setRenderOverride(store, render) {
|
|
14120
|
+
store.getState().internal.renderOverride = render;
|
|
14121
|
+
}
|
|
14122
|
+
function attachRootExtensions(store) {
|
|
14123
|
+
const registry = getRegistry();
|
|
14124
|
+
registry.roots.add(store);
|
|
14125
|
+
for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
|
|
14126
|
+
}
|
|
14127
|
+
function current(registry, setUpBy) {
|
|
14128
|
+
return registry.extensions.get(setUpBy.name) ?? setUpBy;
|
|
14129
|
+
}
|
|
14130
|
+
function detachRootExtensions(store) {
|
|
14131
|
+
const registry = getRegistry();
|
|
14132
|
+
if (!registry.roots.delete(store)) return;
|
|
14133
|
+
const applied = registry.applied.get(store);
|
|
14134
|
+
registry.applied.delete(store);
|
|
14135
|
+
if (!applied) return;
|
|
14136
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
|
|
14137
|
+
}
|
|
14138
|
+
function notifyRootExtensionsHmr(store) {
|
|
14139
|
+
const registry = getRegistry();
|
|
14140
|
+
const applied = registry.applied.get(store);
|
|
14141
|
+
if (!applied) return;
|
|
14142
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
|
|
14143
|
+
}
|
|
14056
14144
|
|
|
14057
14145
|
const isRenderer = (def) => !!def?.render;
|
|
14058
14146
|
const _roots = /* @__PURE__ */ new Map();
|
|
@@ -14287,7 +14375,7 @@ function createRoot(canvas) {
|
|
|
14287
14375
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14288
14376
|
const state2 = store.getState();
|
|
14289
14377
|
if (state2.frameloop === "never") return;
|
|
14290
|
-
advance(timestamp);
|
|
14378
|
+
advance(timestamp, true, state2);
|
|
14291
14379
|
};
|
|
14292
14380
|
const actualRenderer = state.internal.actualRenderer;
|
|
14293
14381
|
const handleSessionChange = () => {
|
|
@@ -14295,7 +14383,7 @@ function createRoot(canvas) {
|
|
|
14295
14383
|
const renderer2 = state2.internal.actualRenderer;
|
|
14296
14384
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14297
14385
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14298
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14386
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14299
14387
|
};
|
|
14300
14388
|
const xr = {
|
|
14301
14389
|
connect() {
|
|
@@ -14377,14 +14465,23 @@ function createRoot(canvas) {
|
|
|
14377
14465
|
const newRootId = canvasId || scheduler.generateRootId();
|
|
14378
14466
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14379
14467
|
getState: () => store.getState(),
|
|
14380
|
-
onError: (err) => store.getState().setError(err)
|
|
14468
|
+
onError: (err) => store.getState().setError(err),
|
|
14469
|
+
frameloop: store.getState().frameloop,
|
|
14470
|
+
before: schedulerConfig?.before,
|
|
14471
|
+
after: schedulerConfig?.after,
|
|
14472
|
+
order: schedulerConfig?.order
|
|
14381
14473
|
});
|
|
14382
14474
|
const unregisterCanvasTarget = scheduler.register(
|
|
14383
14475
|
() => {
|
|
14384
14476
|
const state2 = store.getState();
|
|
14385
|
-
|
|
14477
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14478
|
+
if (canvasTarget) {
|
|
14386
14479
|
const renderer2 = state2.internal.actualRenderer;
|
|
14387
|
-
renderer2.setCanvasTarget(
|
|
14480
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14481
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14482
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14483
|
+
renderer2.backend?.updateSize?.();
|
|
14484
|
+
}
|
|
14388
14485
|
}
|
|
14389
14486
|
},
|
|
14390
14487
|
{
|
|
@@ -14440,7 +14537,8 @@ function createRoot(canvas) {
|
|
|
14440
14537
|
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
14441
14538
|
if (userHandlesRender || state2.internal.priority) return;
|
|
14442
14539
|
try {
|
|
14443
|
-
|
|
14540
|
+
const renderOverride = state2.internal.renderOverride;
|
|
14541
|
+
if (renderOverride) renderOverride();
|
|
14444
14542
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
14445
14543
|
} catch (error) {
|
|
14446
14544
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -14453,8 +14551,7 @@ function createRoot(canvas) {
|
|
|
14453
14551
|
phase: "render",
|
|
14454
14552
|
system: true,
|
|
14455
14553
|
// Internal flag: this is a system job, not user-controlled
|
|
14456
|
-
//
|
|
14457
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14554
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14458
14555
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14459
14556
|
}
|
|
14460
14557
|
);
|
|
@@ -14473,8 +14570,22 @@ function createRoot(canvas) {
|
|
|
14473
14570
|
scheduler
|
|
14474
14571
|
}
|
|
14475
14572
|
}));
|
|
14573
|
+
} else {
|
|
14574
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14575
|
+
if (constraintsChanged) {
|
|
14576
|
+
scheduler.setRootConstraints(rootId, {
|
|
14577
|
+
before: schedulerConfig?.before,
|
|
14578
|
+
after: schedulerConfig?.after
|
|
14579
|
+
});
|
|
14580
|
+
}
|
|
14581
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14582
|
+
scheduler.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14583
|
+
}
|
|
14476
14584
|
}
|
|
14477
|
-
|
|
14585
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14586
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14587
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14588
|
+
attachRootExtensions(store);
|
|
14478
14589
|
onCreated = onCreatedCallback;
|
|
14479
14590
|
configured = true;
|
|
14480
14591
|
resolve();
|
|
@@ -14516,18 +14627,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14516
14627
|
const fiber = root?.fiber;
|
|
14517
14628
|
if (fiber) {
|
|
14518
14629
|
const state = root?.store.getState();
|
|
14519
|
-
if (state)
|
|
14630
|
+
if (state) {
|
|
14631
|
+
state.internal.active = false;
|
|
14632
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14633
|
+
if (unregisterRoot) {
|
|
14634
|
+
unregisterRoot();
|
|
14635
|
+
state.internal.unregisterRoot = void 0;
|
|
14636
|
+
}
|
|
14637
|
+
}
|
|
14520
14638
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14639
|
+
if (root?.store) detachRootExtensions(root.store);
|
|
14521
14640
|
if (state) {
|
|
14522
14641
|
setTimeout(() => {
|
|
14523
14642
|
try {
|
|
14524
14643
|
const renderer = state.internal.actualRenderer;
|
|
14525
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14526
|
-
if (unregisterRoot) unregisterRoot();
|
|
14527
14644
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14528
14645
|
if (unregisterPrimary) unregisterPrimary();
|
|
14529
14646
|
const canvasTarget = state.internal.canvasTarget;
|
|
14530
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14647
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14531
14648
|
state.events.disconnect?.();
|
|
14532
14649
|
cleanupHelperGroup(root.store);
|
|
14533
14650
|
if (state.isLegacy && renderer) {
|
|
@@ -14668,16 +14785,11 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14668
14785
|
const oldbg = target.background;
|
|
14669
14786
|
const oldenv = target.environment;
|
|
14670
14787
|
const oldSceneProps = {
|
|
14671
|
-
// @ts-ignore
|
|
14672
14788
|
backgroundBlurriness: target.backgroundBlurriness,
|
|
14673
|
-
// @ts-ignore
|
|
14674
14789
|
backgroundIntensity: target.backgroundIntensity,
|
|
14675
|
-
|
|
14676
|
-
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
14677
|
-
// @ts-ignore
|
|
14790
|
+
backgroundRotation: target.backgroundRotation.clone(),
|
|
14678
14791
|
environmentIntensity: target.environmentIntensity,
|
|
14679
|
-
|
|
14680
|
-
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
14792
|
+
environmentRotation: target.environmentRotation.clone()
|
|
14681
14793
|
};
|
|
14682
14794
|
if (background !== "only") target.environment = texture;
|
|
14683
14795
|
if (background) target.background = texture;
|
|
@@ -14689,7 +14801,7 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14689
14801
|
};
|
|
14690
14802
|
}
|
|
14691
14803
|
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
14692
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14804
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14693
14805
|
React.useLayoutEffect(() => {
|
|
14694
14806
|
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
14695
14807
|
});
|
|
@@ -14707,7 +14819,7 @@ function EnvironmentCube({
|
|
|
14707
14819
|
...rest
|
|
14708
14820
|
}) {
|
|
14709
14821
|
const texture = useEnvironment(rest);
|
|
14710
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14822
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14711
14823
|
React.useLayoutEffect(() => {
|
|
14712
14824
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
14713
14825
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -14744,9 +14856,9 @@ function EnvironmentPortal({
|
|
|
14744
14856
|
preset = void 0,
|
|
14745
14857
|
extensions
|
|
14746
14858
|
}) {
|
|
14747
|
-
const renderer = useThree((state) => state.renderer);
|
|
14748
|
-
const isLegacy = useThree((state) => state.isLegacy);
|
|
14749
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14859
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
14860
|
+
const isLegacy = useThree$1((state) => state.isLegacy);
|
|
14861
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14750
14862
|
const camera = React.useRef(null);
|
|
14751
14863
|
const [virtualScene] = React.useState(() => new Scene());
|
|
14752
14864
|
const fbo = React.useMemo(() => {
|
|
@@ -14790,7 +14902,7 @@ function EnvironmentPortal({
|
|
|
14790
14902
|
environmentRotation
|
|
14791
14903
|
]);
|
|
14792
14904
|
let count = 1;
|
|
14793
|
-
useFrame(() => {
|
|
14905
|
+
useFrame$1(() => {
|
|
14794
14906
|
if (frames === Infinity || count < frames) {
|
|
14795
14907
|
const autoClear = renderer.autoClear;
|
|
14796
14908
|
renderer.autoClear = true;
|
|
@@ -14830,7 +14942,7 @@ function EnvironmentGround(props) {
|
|
|
14830
14942
|
] });
|
|
14831
14943
|
}
|
|
14832
14944
|
function EnvironmentColor({ color, scene }) {
|
|
14833
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14945
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14834
14946
|
React.useLayoutEffect(() => {
|
|
14835
14947
|
if (color === void 0) return;
|
|
14836
14948
|
const target = resolveScene(scene || defaultScene);
|
|
@@ -14902,38 +15014,6 @@ function parseRendererConfig(rendererProp) {
|
|
|
14902
15014
|
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
14903
15015
|
}
|
|
14904
15016
|
|
|
14905
|
-
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
14906
|
-
const registries = /* @__PURE__ */ new WeakMap();
|
|
14907
|
-
function getKindRegistry(store, kind) {
|
|
14908
|
-
let registry = registries.get(store);
|
|
14909
|
-
if (!registry) {
|
|
14910
|
-
registry = {
|
|
14911
|
-
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14912
|
-
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14913
|
-
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14914
|
-
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
14915
|
-
};
|
|
14916
|
-
registries.set(store, registry);
|
|
14917
|
-
}
|
|
14918
|
-
return registry[kind];
|
|
14919
|
-
}
|
|
14920
|
-
function invalidateResource(store, kind, scopeKey) {
|
|
14921
|
-
const registry = getKindRegistry(store, kind);
|
|
14922
|
-
{
|
|
14923
|
-
registry.valid.clear();
|
|
14924
|
-
registry.staged.clear();
|
|
14925
|
-
}
|
|
14926
|
-
}
|
|
14927
|
-
function invalidateAllResources(store) {
|
|
14928
|
-
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
14929
|
-
}
|
|
14930
|
-
|
|
14931
|
-
function clearHmrCaches(store) {
|
|
14932
|
-
const primary = store.getState().primaryStore ?? store;
|
|
14933
|
-
invalidateAllResources(primary);
|
|
14934
|
-
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
14935
|
-
}
|
|
14936
|
-
|
|
14937
15017
|
function CanvasImpl({
|
|
14938
15018
|
ref,
|
|
14939
15019
|
children,
|
|
@@ -14971,9 +15051,9 @@ function CanvasImpl({
|
|
|
14971
15051
|
React.useMemo(() => extend(THREE), []);
|
|
14972
15052
|
const Bridge = useBridge();
|
|
14973
15053
|
const backgroundProps = React.useMemo(() => parseBackground(background), [background]);
|
|
14974
|
-
const
|
|
15054
|
+
const [hasInitialSize, setHasInitialSize] = React.useState(false);
|
|
14975
15055
|
const measureConfig = React.useMemo(() => {
|
|
14976
|
-
if (!
|
|
15056
|
+
if (!hasInitialSize) {
|
|
14977
15057
|
return {
|
|
14978
15058
|
...resize,
|
|
14979
15059
|
scroll: resize?.scroll ?? true,
|
|
@@ -14985,7 +15065,7 @@ function CanvasImpl({
|
|
|
14985
15065
|
debounce: { scroll: 50, resize: 0 },
|
|
14986
15066
|
...resize
|
|
14987
15067
|
};
|
|
14988
|
-
}, [
|
|
15068
|
+
}, [hasInitialSize, resize]);
|
|
14989
15069
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
14990
15070
|
const effectiveSize = React.useMemo(() => {
|
|
14991
15071
|
let w = width ?? containerRect.width;
|
|
@@ -15001,9 +15081,7 @@ function CanvasImpl({
|
|
|
15001
15081
|
left: containerRect.left
|
|
15002
15082
|
};
|
|
15003
15083
|
}, [width, height, containerRect, forceEven]);
|
|
15004
|
-
if (!
|
|
15005
|
-
hasInitialSizeRef.current = true;
|
|
15006
|
-
}
|
|
15084
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15007
15085
|
const canvasRef = React.useRef(null);
|
|
15008
15086
|
const divRef = React.useRef(null);
|
|
15009
15087
|
React.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15117,6 +15195,7 @@ function CanvasImpl({
|
|
|
15117
15195
|
const canvas = canvasRef.current;
|
|
15118
15196
|
if (canvas) {
|
|
15119
15197
|
return () => {
|
|
15198
|
+
if (canvas.isConnected) return;
|
|
15120
15199
|
unmountComponentAtNode(canvas);
|
|
15121
15200
|
root.current = null;
|
|
15122
15201
|
};
|
|
@@ -15129,7 +15208,7 @@ function CanvasImpl({
|
|
|
15129
15208
|
const handleHMR = () => {
|
|
15130
15209
|
queueMicrotask(() => {
|
|
15131
15210
|
const rootEntry = _roots.get(canvas);
|
|
15132
|
-
if (rootEntry?.store)
|
|
15211
|
+
if (rootEntry?.store) notifyRootExtensionsHmr(rootEntry.store);
|
|
15133
15212
|
});
|
|
15134
15213
|
};
|
|
15135
15214
|
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
@@ -15175,10 +15254,13 @@ function CanvasImpl({
|
|
|
15175
15254
|
}
|
|
15176
15255
|
);
|
|
15177
15256
|
}
|
|
15178
|
-
function Canvas(props) {
|
|
15257
|
+
function Canvas$1(props) {
|
|
15179
15258
|
return /* @__PURE__ */ jsx(FiberProvider, { children: /* @__PURE__ */ jsx(CanvasImpl, { ...props }) });
|
|
15180
15259
|
}
|
|
15181
15260
|
|
|
15182
15261
|
extend(THREE);
|
|
15262
|
+
const useThree = useThree$1;
|
|
15263
|
+
const useFrame = useFrame$1;
|
|
15264
|
+
const Canvas = Canvas$1;
|
|
15183
15265
|
|
|
15184
|
-
export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Texture, _roots, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef$1 as isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, reconciler, registerPrimary, removeInteractivity, resolve, swapInteractivity, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree, waitForPrimary };
|
|
15266
|
+
export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Texture, _roots, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef$1 as isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, reconciler, registerPrimary, registerRootExtension, removeInteractivity, resolve, setRenderOverride, swapInteractivity, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree, waitForPrimary };
|