@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.cjs
CHANGED
|
@@ -10,6 +10,7 @@ const scheduler = require('@pmndrs/scheduler');
|
|
|
10
10
|
const Tb = require('scheduler');
|
|
11
11
|
const GroundedSkybox_js = require('three/examples/jsm/objects/GroundedSkybox.js');
|
|
12
12
|
const HDRLoader_js = require('three/examples/jsm/loaders/HDRLoader.js');
|
|
13
|
+
const HDRCubeTextureLoader_js = require('three/examples/jsm/loaders/HDRCubeTextureLoader.js');
|
|
13
14
|
const EXRLoader_js = require('three/examples/jsm/loaders/EXRLoader.js');
|
|
14
15
|
const UltraHDRLoader_js = require('three/examples/jsm/loaders/UltraHDRLoader.js');
|
|
15
16
|
const gainmapJs = require('@monogrid/gainmap-js');
|
|
@@ -50,16 +51,14 @@ const Tb__default = /*#__PURE__*/_interopDefaultCompat(Tb);
|
|
|
50
51
|
|
|
51
52
|
const R3F_BUILD_LEGACY = true;
|
|
52
53
|
const R3F_BUILD_WEBGPU = false;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
};
|
|
58
|
-
const WebGPURenderer = class WebGPURenderer2 {
|
|
54
|
+
async function loadInspector() {
|
|
55
|
+
throw new Error("Inspector is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
56
|
+
}
|
|
57
|
+
class WebGPURenderer {
|
|
59
58
|
constructor() {
|
|
60
59
|
throw new Error("WebGPURenderer is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
61
60
|
}
|
|
62
|
-
}
|
|
61
|
+
}
|
|
63
62
|
const RenderTarget = null;
|
|
64
63
|
const CubeRenderTarget = null;
|
|
65
64
|
|
|
@@ -67,12 +66,12 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
67
66
|
__proto__: null,
|
|
68
67
|
CubeRenderTarget: CubeRenderTarget,
|
|
69
68
|
CubeRenderTargetCompat: three.WebGLCubeRenderTarget,
|
|
70
|
-
Inspector: Inspector,
|
|
71
69
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
72
70
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
73
71
|
RenderTarget: RenderTarget,
|
|
74
72
|
RenderTargetCompat: three.WebGLRenderTarget,
|
|
75
|
-
WebGPURenderer: WebGPURenderer
|
|
73
|
+
WebGPURenderer: WebGPURenderer,
|
|
74
|
+
loadInspector: loadInspector
|
|
76
75
|
}, [three__namespace]);
|
|
77
76
|
|
|
78
77
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -319,7 +318,6 @@ function prepare(target, root, type, props) {
|
|
|
319
318
|
}
|
|
320
319
|
function invalidateInstance(instance) {
|
|
321
320
|
if (!instance.parent) return;
|
|
322
|
-
instance.props.onUpdate?.(instance.object);
|
|
323
321
|
const state = instance.root?.getState?.();
|
|
324
322
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
325
323
|
}
|
|
@@ -535,8 +533,10 @@ function hasVisibilityHandlers(handlers) {
|
|
|
535
533
|
}
|
|
536
534
|
|
|
537
535
|
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
538
|
-
function fromRef(ref) {
|
|
539
|
-
|
|
536
|
+
function fromRef(ref, transform) {
|
|
537
|
+
const marker = { [FROM_REF]: ref };
|
|
538
|
+
if (transform) marker.transform = transform;
|
|
539
|
+
return marker;
|
|
540
540
|
}
|
|
541
541
|
function isFromRef(value) {
|
|
542
542
|
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
@@ -550,6 +550,63 @@ function isOnce(value) {
|
|
|
550
550
|
return value !== null && typeof value === "object" && ONCE in value;
|
|
551
551
|
}
|
|
552
552
|
|
|
553
|
+
const shownNotices = /* @__PURE__ */ new Set();
|
|
554
|
+
function notifyDepreciated({ heading, body, link }) {
|
|
555
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (shownNotices.has(heading)) return;
|
|
559
|
+
shownNotices.add(heading);
|
|
560
|
+
const caller = getCallerFrame();
|
|
561
|
+
if (caller) {
|
|
562
|
+
console.log();
|
|
563
|
+
}
|
|
564
|
+
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
565
|
+
if (caller) {
|
|
566
|
+
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
567
|
+
}
|
|
568
|
+
if (body || link) {
|
|
569
|
+
let message = "";
|
|
570
|
+
if (body) message += body;
|
|
571
|
+
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
572
|
+
console.warn(`%c${message}`, "font-weight: bold;");
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function getCallerFrame(depth = 3) {
|
|
576
|
+
const stack = new Error().stack;
|
|
577
|
+
if (!stack) return null;
|
|
578
|
+
const lines = stack.split("\n");
|
|
579
|
+
const frame = lines[depth];
|
|
580
|
+
if (!frame) return null;
|
|
581
|
+
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
582
|
+
if (!match) {
|
|
583
|
+
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
584
|
+
}
|
|
585
|
+
if (!match) return null;
|
|
586
|
+
const [, fn, url, line] = match;
|
|
587
|
+
return {
|
|
588
|
+
functionName: fn ?? "<anonymous>",
|
|
589
|
+
location: formatLocation(url, Number(line))
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
function formatLocation(url, line) {
|
|
593
|
+
const clean = url.split("?")[0];
|
|
594
|
+
const file = clean.split("/").pop() ?? clean;
|
|
595
|
+
return `${file}:${line}`;
|
|
596
|
+
}
|
|
597
|
+
function notifyAlpha({ message, link }) {
|
|
598
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
if (shownNotices.has(message)) return;
|
|
602
|
+
shownNotices.add(message);
|
|
603
|
+
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
604
|
+
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
605
|
+
{
|
|
606
|
+
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
553
610
|
const RESERVED_PROPS = [
|
|
554
611
|
"children",
|
|
555
612
|
"key",
|
|
@@ -559,7 +616,6 @@ const RESERVED_PROPS = [
|
|
|
559
616
|
"dispose",
|
|
560
617
|
"attach",
|
|
561
618
|
"object",
|
|
562
|
-
"onUpdate",
|
|
563
619
|
// Behavior flags
|
|
564
620
|
"dispose"
|
|
565
621
|
];
|
|
@@ -637,11 +693,9 @@ function diffProps(instance, newProps) {
|
|
|
637
693
|
for (const prop in instance.props) {
|
|
638
694
|
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
639
695
|
const { root, key } = resolve(instance.object, prop);
|
|
640
|
-
if (
|
|
696
|
+
if (typeof root?.constructor === "function") {
|
|
641
697
|
const ctor = getMemoizedPrototype(root);
|
|
642
698
|
if (!is.und(ctor)) changedProps[prop] = ctor[key];
|
|
643
|
-
} else {
|
|
644
|
-
changedProps[prop] = 0;
|
|
645
699
|
}
|
|
646
700
|
}
|
|
647
701
|
return changedProps;
|
|
@@ -653,6 +707,13 @@ function applyProps(object, props) {
|
|
|
653
707
|
for (const prop in props) {
|
|
654
708
|
const value = props[prop];
|
|
655
709
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
710
|
+
if (prop === "onUpdate") {
|
|
711
|
+
notifyDepreciated({
|
|
712
|
+
heading: "onUpdate is no longer an R3F prop",
|
|
713
|
+
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.",
|
|
714
|
+
link: "https://docs.pmnd.rs/react-three-fiber/migration/v10#onupdate-removed"
|
|
715
|
+
});
|
|
716
|
+
}
|
|
656
717
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
657
718
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
658
719
|
else delete instance.handlers[prop];
|
|
@@ -758,682 +819,378 @@ function applyProps(object, props) {
|
|
|
758
819
|
return object;
|
|
759
820
|
}
|
|
760
821
|
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
if (
|
|
767
|
-
|
|
768
|
-
const caller = getCallerFrame();
|
|
769
|
-
if (caller) {
|
|
770
|
-
console.log();
|
|
771
|
-
}
|
|
772
|
-
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
773
|
-
if (caller) {
|
|
774
|
-
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
775
|
-
}
|
|
776
|
-
if (body || link) {
|
|
777
|
-
let message = "";
|
|
778
|
-
if (body) message += body;
|
|
779
|
-
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
780
|
-
console.warn(`%c${message}`, "font-weight: bold;");
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
function getCallerFrame(depth = 3) {
|
|
784
|
-
const stack = new Error().stack;
|
|
785
|
-
if (!stack) return null;
|
|
786
|
-
const lines = stack.split("\n");
|
|
787
|
-
const frame = lines[depth];
|
|
788
|
-
if (!frame) return null;
|
|
789
|
-
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
790
|
-
if (!match) {
|
|
791
|
-
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
792
|
-
}
|
|
793
|
-
if (!match) return null;
|
|
794
|
-
const [, fn, url, line] = match;
|
|
795
|
-
return {
|
|
796
|
-
functionName: fn ?? "<anonymous>",
|
|
797
|
-
location: formatLocation(url, Number(line))
|
|
798
|
-
};
|
|
822
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
823
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React__namespace.createContext(null));
|
|
824
|
+
|
|
825
|
+
function useStore() {
|
|
826
|
+
const store = React.useContext(context);
|
|
827
|
+
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
828
|
+
return store;
|
|
799
829
|
}
|
|
800
|
-
function
|
|
801
|
-
|
|
802
|
-
const file = clean.split("/").pop() ?? clean;
|
|
803
|
-
return `${file}:${line}`;
|
|
830
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
831
|
+
return useStore()(selector, equalityFn);
|
|
804
832
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
if (
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
833
|
+
|
|
834
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
835
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
836
|
+
function getLoader$1(Proto) {
|
|
837
|
+
if (isConstructor$1(Proto)) {
|
|
838
|
+
let loader = memoizedLoaders.get(Proto);
|
|
839
|
+
if (!loader) {
|
|
840
|
+
loader = new Proto();
|
|
841
|
+
memoizedLoaders.set(Proto, loader);
|
|
842
|
+
}
|
|
843
|
+
return loader;
|
|
815
844
|
}
|
|
845
|
+
return Proto;
|
|
816
846
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
847
|
+
function loadingFn(extensions, onProgress) {
|
|
848
|
+
return function(Proto, input) {
|
|
849
|
+
const loader = getLoader$1(Proto);
|
|
850
|
+
if (extensions) extensions(loader);
|
|
851
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
852
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
853
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
854
|
+
return data;
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
return new Promise(
|
|
858
|
+
(res, reject) => loader.load(
|
|
859
|
+
input,
|
|
860
|
+
(data) => {
|
|
861
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
862
|
+
res(data);
|
|
863
|
+
},
|
|
864
|
+
onProgress,
|
|
865
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
866
|
+
)
|
|
867
|
+
);
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
871
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
872
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
873
|
+
const fn = loadingFn(extensions, onProgress);
|
|
874
|
+
const results = cacheKeys.map(
|
|
875
|
+
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
876
|
+
);
|
|
877
|
+
const stableRef = React.useRef(null);
|
|
878
|
+
const previous = stableRef.current;
|
|
879
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
880
|
+
stableRef.current = stable;
|
|
881
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
823
882
|
}
|
|
883
|
+
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
884
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
885
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
886
|
+
cacheKeys.forEach(
|
|
887
|
+
(key, index) => suspendReact.preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
888
|
+
);
|
|
889
|
+
};
|
|
890
|
+
useLoader.clear = function(loader, input, cacheKey) {
|
|
891
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
892
|
+
cacheKeys.forEach((key) => suspendReact.clear([loader, key]));
|
|
893
|
+
};
|
|
894
|
+
useLoader.loader = getLoader$1;
|
|
824
895
|
|
|
825
|
-
|
|
826
|
-
const
|
|
827
|
-
const
|
|
828
|
-
const
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
896
|
+
function useFrame$1(callback, priorityOrOptions) {
|
|
897
|
+
const store = React__namespace.useContext(context);
|
|
898
|
+
const isInsideCanvas = store !== null;
|
|
899
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
900
|
+
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
901
|
+
id: priorityOrOptions.id,
|
|
902
|
+
phase: priorityOrOptions.phase,
|
|
903
|
+
priority: priorityOrOptions.priority,
|
|
904
|
+
fps: priorityOrOptions.fps,
|
|
905
|
+
drop: priorityOrOptions.drop,
|
|
906
|
+
enabled: priorityOrOptions.enabled,
|
|
907
|
+
before: priorityOrOptions.before,
|
|
908
|
+
after: priorityOrOptions.after
|
|
909
|
+
}) : "";
|
|
910
|
+
const options = React__namespace.useMemo(() => {
|
|
911
|
+
return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
|
|
912
|
+
}, [optionsKey]);
|
|
913
|
+
const reactId = React__namespace.useId();
|
|
914
|
+
const id = options.id ?? reactId;
|
|
915
|
+
const callbackRef = useMutableCallback(callback);
|
|
916
|
+
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
917
|
+
useIsomorphicLayoutEffect(() => {
|
|
918
|
+
if (!callback) return;
|
|
919
|
+
if (isInsideCanvas) {
|
|
920
|
+
const state = store.getState();
|
|
921
|
+
const rootId = state.internal.rootId;
|
|
922
|
+
if (isLegacyPriority) {
|
|
923
|
+
state.internal.priority++;
|
|
924
|
+
let parentRoot = state.previousRoot;
|
|
925
|
+
while (parentRoot) {
|
|
926
|
+
const parentState = parentRoot.getState();
|
|
927
|
+
if (parentState?.internal) parentState.internal.priority++;
|
|
928
|
+
parentRoot = parentState?.previousRoot;
|
|
929
|
+
}
|
|
930
|
+
notifyDepreciated({
|
|
931
|
+
heading: "useFrame with numeric priority is deprecated",
|
|
932
|
+
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 })',
|
|
933
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
934
|
+
});
|
|
845
935
|
}
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
inspector: null,
|
|
874
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
875
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
876
|
-
textureColorSpace: three.SRGBColorSpace,
|
|
877
|
-
isLegacy: false,
|
|
878
|
-
webGPUSupported: false,
|
|
879
|
-
isNative: false,
|
|
880
|
-
controls: null,
|
|
881
|
-
pointer,
|
|
882
|
-
mouse: pointer,
|
|
883
|
-
frameloop: "always",
|
|
884
|
-
onPointerMissed: void 0,
|
|
885
|
-
onDragOverMissed: void 0,
|
|
886
|
-
onDropMissed: void 0,
|
|
887
|
-
performance: {
|
|
888
|
-
current: 1,
|
|
889
|
-
min: 0.5,
|
|
890
|
-
max: 1,
|
|
891
|
-
debounce: 200,
|
|
892
|
-
regress: () => {
|
|
893
|
-
const state2 = get();
|
|
894
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
895
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
896
|
-
performanceTimeout = setTimeout(
|
|
897
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
898
|
-
state2.performance.debounce
|
|
899
|
-
);
|
|
900
|
-
}
|
|
901
|
-
},
|
|
902
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
903
|
-
viewport: {
|
|
904
|
-
initialDpr: 0,
|
|
905
|
-
dpr: 0,
|
|
906
|
-
width: 0,
|
|
907
|
-
height: 0,
|
|
908
|
-
top: 0,
|
|
909
|
-
left: 0,
|
|
910
|
-
aspect: 0,
|
|
911
|
-
distance: 0,
|
|
912
|
-
factor: 0,
|
|
913
|
-
getCurrentViewport
|
|
914
|
-
},
|
|
915
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
916
|
-
setSize: (width, height, top, left) => {
|
|
917
|
-
const state2 = get();
|
|
918
|
-
if (width === void 0) {
|
|
919
|
-
set({ _sizeImperative: false });
|
|
920
|
-
if (state2._sizeProps) {
|
|
921
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
922
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
923
|
-
const currentSize = state2.size;
|
|
924
|
-
const newSize = {
|
|
925
|
-
width: propW ?? currentSize.width,
|
|
926
|
-
height: propH ?? currentSize.height,
|
|
927
|
-
top: currentSize.top,
|
|
928
|
-
left: currentSize.left
|
|
929
|
-
};
|
|
930
|
-
set((s) => ({
|
|
931
|
-
size: newSize,
|
|
932
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
933
|
-
}));
|
|
934
|
-
scheduler.getScheduler().invalidate();
|
|
936
|
+
const wrappedCallback = (frameState, delta) => {
|
|
937
|
+
const localState = store.getState();
|
|
938
|
+
const mergedState = {
|
|
939
|
+
...localState,
|
|
940
|
+
time: frameState.time,
|
|
941
|
+
delta: frameState.delta,
|
|
942
|
+
elapsed: frameState.elapsed,
|
|
943
|
+
frame: frameState.frame
|
|
944
|
+
};
|
|
945
|
+
callbackRef.current?.(mergedState, delta);
|
|
946
|
+
};
|
|
947
|
+
const unregister = scheduler$1.register(wrappedCallback, {
|
|
948
|
+
id,
|
|
949
|
+
rootId,
|
|
950
|
+
...options
|
|
951
|
+
});
|
|
952
|
+
return () => {
|
|
953
|
+
unregister();
|
|
954
|
+
if (isLegacyPriority) {
|
|
955
|
+
const currentState = store.getState();
|
|
956
|
+
if (currentState.internal) {
|
|
957
|
+
currentState.internal.priority--;
|
|
958
|
+
let parentRoot = currentState.previousRoot;
|
|
959
|
+
while (parentRoot) {
|
|
960
|
+
const parentState = parentRoot.getState();
|
|
961
|
+
if (parentState?.internal) parentState.internal.priority--;
|
|
962
|
+
parentRoot = parentState?.previousRoot;
|
|
935
963
|
}
|
|
936
964
|
}
|
|
937
|
-
return;
|
|
938
965
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
966
|
+
};
|
|
967
|
+
} else {
|
|
968
|
+
return scheduler$1.register(
|
|
969
|
+
(state, delta) => {
|
|
970
|
+
const frameState = state;
|
|
971
|
+
if (!frameState.renderer) return;
|
|
972
|
+
callbackRef.current?.(frameState, delta);
|
|
973
|
+
},
|
|
974
|
+
{ id, ...options }
|
|
975
|
+
);
|
|
976
|
+
}
|
|
977
|
+
}, [store, scheduler$1, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
978
|
+
const isPaused = React__namespace.useSyncExternalStore(
|
|
979
|
+
// Subscribe function
|
|
980
|
+
React__namespace.useCallback(
|
|
981
|
+
(onStoreChange) => {
|
|
982
|
+
return scheduler.getScheduler().subscribeJobState(id, onStoreChange);
|
|
950
983
|
},
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
984
|
+
[id]
|
|
985
|
+
),
|
|
986
|
+
// getSnapshot function
|
|
987
|
+
React__namespace.useCallback(() => scheduler.getScheduler().isJobPaused(id), [id]),
|
|
988
|
+
// getServerSnapshot function (SSR)
|
|
989
|
+
React__namespace.useCallback(() => false, [])
|
|
990
|
+
);
|
|
991
|
+
const controls = React__namespace.useMemo(() => {
|
|
992
|
+
const scheduler2 = scheduler.getScheduler();
|
|
993
|
+
return {
|
|
994
|
+
/** The job's unique ID */
|
|
995
|
+
id,
|
|
996
|
+
/**
|
|
997
|
+
* Access to the global scheduler for frame loop control.
|
|
998
|
+
* Use for controlling the entire frame loop, adding phases, etc.
|
|
999
|
+
*/
|
|
1000
|
+
scheduler: scheduler2,
|
|
1001
|
+
/**
|
|
1002
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
1003
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1004
|
+
*/
|
|
1005
|
+
get rootId() {
|
|
1006
|
+
return scheduler.getScheduler().getJobRootId(id);
|
|
958
1007
|
},
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
internal.subscribers.push({ ref, priority, store });
|
|
1002
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1003
|
-
return () => {
|
|
1004
|
-
const internal2 = get().internal;
|
|
1005
|
-
if (internal2?.subscribers) {
|
|
1006
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
1007
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
1008
|
-
}
|
|
1009
|
-
};
|
|
1010
|
-
},
|
|
1011
|
-
// Renderer Storage (single source of truth)
|
|
1012
|
-
actualRenderer: null,
|
|
1013
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
1014
|
-
scheduler: null
|
|
1015
|
-
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Manually step this job only.
|
|
1010
|
+
* Bypasses FPS limiting - always runs.
|
|
1011
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1012
|
+
*/
|
|
1013
|
+
step: (timestamp) => {
|
|
1014
|
+
scheduler.getScheduler().stepJob(id, timestamp);
|
|
1015
|
+
},
|
|
1016
|
+
/**
|
|
1017
|
+
* Manually step ALL jobs in the scheduler.
|
|
1018
|
+
* Useful for frameloop='never' mode.
|
|
1019
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1020
|
+
*/
|
|
1021
|
+
stepAll: (timestamp) => {
|
|
1022
|
+
scheduler.getScheduler().step(timestamp);
|
|
1023
|
+
},
|
|
1024
|
+
/**
|
|
1025
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1026
|
+
*/
|
|
1027
|
+
invalidate: (frames, stackFrames) => {
|
|
1028
|
+
const scheduler3 = scheduler.getScheduler();
|
|
1029
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1030
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1031
|
+
},
|
|
1032
|
+
/**
|
|
1033
|
+
* Pause this job (set enabled=false).
|
|
1034
|
+
* Job remains registered but won't run.
|
|
1035
|
+
*/
|
|
1036
|
+
pause: () => {
|
|
1037
|
+
scheduler.getScheduler().pauseJob(id);
|
|
1038
|
+
},
|
|
1039
|
+
/**
|
|
1040
|
+
* Resume this job (set enabled=true).
|
|
1041
|
+
*/
|
|
1042
|
+
resume: () => {
|
|
1043
|
+
scheduler.getScheduler().resumeJob(id);
|
|
1044
|
+
},
|
|
1045
|
+
/**
|
|
1046
|
+
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1047
|
+
* No need for forceUpdate() in your components.
|
|
1048
|
+
*/
|
|
1049
|
+
isPaused
|
|
1016
1050
|
};
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
Object.defineProperty(state, "gl", {
|
|
1021
|
-
get() {
|
|
1022
|
-
const currentState = rootStore.getState();
|
|
1023
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1024
|
-
const stack = new Error().stack || "";
|
|
1025
|
-
if (!isInternalRendererAccess(stack)) {
|
|
1026
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1027
|
-
notifyDepreciated({
|
|
1028
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1029
|
-
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
|
|
1030
|
-
});
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
return currentState.internal.actualRenderer;
|
|
1034
|
-
},
|
|
1035
|
-
set(value) {
|
|
1036
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1037
|
-
},
|
|
1038
|
-
enumerable: true,
|
|
1039
|
-
configurable: true
|
|
1040
|
-
});
|
|
1041
|
-
Object.defineProperty(state, "renderer", {
|
|
1042
|
-
get() {
|
|
1043
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1044
|
-
},
|
|
1045
|
-
set(value) {
|
|
1046
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1047
|
-
},
|
|
1048
|
-
enumerable: true,
|
|
1049
|
-
configurable: true
|
|
1050
|
-
});
|
|
1051
|
-
let oldScene = state.scene;
|
|
1052
|
-
rootStore.subscribe(() => {
|
|
1053
|
-
const currentState = rootStore.getState();
|
|
1054
|
-
const { scene, rootScene, set } = currentState;
|
|
1055
|
-
if (scene !== oldScene) {
|
|
1056
|
-
oldScene = scene;
|
|
1057
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1058
|
-
set({ rootScene: scene });
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
});
|
|
1062
|
-
let oldSize = state.size;
|
|
1063
|
-
let oldDpr = state.viewport.dpr;
|
|
1064
|
-
let oldCamera = state.camera;
|
|
1065
|
-
rootStore.subscribe(() => {
|
|
1066
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1067
|
-
const actualRenderer = internal.actualRenderer;
|
|
1068
|
-
const canvasTarget = internal.canvasTarget;
|
|
1069
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1070
|
-
oldSize = size;
|
|
1071
|
-
oldDpr = viewport.dpr;
|
|
1072
|
-
updateCamera(camera, size);
|
|
1073
|
-
if (internal.isSecondary && canvasTarget) {
|
|
1074
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1075
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1076
|
-
} else {
|
|
1077
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1078
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1079
|
-
if (canvasTarget) {
|
|
1080
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1081
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
if (camera !== oldCamera) {
|
|
1086
|
-
oldCamera = camera;
|
|
1087
|
-
const { rootScene } = rootStore.getState();
|
|
1088
|
-
if (camera && rootScene && !camera.parent) {
|
|
1089
|
-
rootScene.add(camera);
|
|
1090
|
-
}
|
|
1091
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1092
|
-
const currentState = rootStore.getState();
|
|
1093
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1094
|
-
updateFrustum(camera, currentState.frustum);
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
});
|
|
1098
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
1099
|
-
return rootStore;
|
|
1100
|
-
};
|
|
1051
|
+
}, [id, isPaused]);
|
|
1052
|
+
return controls;
|
|
1053
|
+
}
|
|
1101
1054
|
|
|
1102
|
-
const
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
if (
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1055
|
+
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1056
|
+
function getUrls(input) {
|
|
1057
|
+
if (typeof input === "string") return [input];
|
|
1058
|
+
if (Array.isArray(input)) return input;
|
|
1059
|
+
return Object.values(input);
|
|
1060
|
+
}
|
|
1061
|
+
function inputSignature(input) {
|
|
1062
|
+
if (typeof input === "string") return input;
|
|
1063
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1064
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1065
|
+
}
|
|
1066
|
+
function allUrlsCached(urls, textureCache) {
|
|
1067
|
+
return urls.every((url) => textureCache.has(url));
|
|
1068
|
+
}
|
|
1069
|
+
function buildFromCache(input, textureCache) {
|
|
1070
|
+
if (typeof input === "string") {
|
|
1071
|
+
return textureCache.get(input);
|
|
1072
|
+
} else if (Array.isArray(input)) {
|
|
1073
|
+
return input.map((url) => textureCache.get(url));
|
|
1074
|
+
} else {
|
|
1075
|
+
const result = {};
|
|
1076
|
+
const objInput = input;
|
|
1077
|
+
for (const key in objInput) {
|
|
1078
|
+
result[key] = textureCache.get(objInput[key]);
|
|
1110
1079
|
}
|
|
1111
|
-
return
|
|
1080
|
+
return result;
|
|
1112
1081
|
}
|
|
1113
|
-
return Proto;
|
|
1114
1082
|
}
|
|
1115
|
-
function
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1083
|
+
function useTexture(input, optionsOrOnLoad) {
|
|
1084
|
+
const renderer = useThree$1((state) => state.internal.actualRenderer);
|
|
1085
|
+
const store = useStore();
|
|
1086
|
+
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1087
|
+
const { onLoad, cache = true } = options;
|
|
1088
|
+
const onLoadRef = React.useRef(onLoad);
|
|
1089
|
+
onLoadRef.current = onLoad;
|
|
1090
|
+
const onLoadCalledForRef = React.useRef(null);
|
|
1091
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
1092
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
1093
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1094
|
+
const cachedResult = React.useMemo(() => {
|
|
1095
|
+
if (!cache) return null;
|
|
1096
|
+
const textures = store.getState().textures;
|
|
1097
|
+
if (!allUrlsCached(urls, textures)) return null;
|
|
1098
|
+
return buildFromCache(stableInput, textures);
|
|
1099
|
+
}, [cache, urls, stableInput, store]);
|
|
1100
|
+
const loadedTextures = useLoader(
|
|
1101
|
+
three.TextureLoader,
|
|
1102
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1103
|
+
);
|
|
1104
|
+
const mappedTextures = React.useMemo(() => {
|
|
1105
|
+
if (cachedResult) return cachedResult;
|
|
1106
|
+
if (IsObject(stableInput)) {
|
|
1107
|
+
const keyed = {};
|
|
1108
|
+
const textureArray = loadedTextures;
|
|
1109
|
+
let i = 0;
|
|
1110
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1111
|
+
return keyed;
|
|
1112
|
+
} else {
|
|
1113
|
+
return loadedTextures;
|
|
1114
|
+
}
|
|
1115
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1116
|
+
React.useLayoutEffect(() => {
|
|
1117
|
+
if (cachedResult) return;
|
|
1118
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
1119
|
+
onLoadCalledForRef.current = inputKey;
|
|
1120
|
+
onLoadRef.current?.(mappedTextures);
|
|
1121
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
1122
|
+
React.useEffect(() => {
|
|
1123
|
+
if (cachedResult) return;
|
|
1124
|
+
if ("initTexture" in renderer) {
|
|
1125
|
+
let textureArray = [];
|
|
1126
|
+
if (Array.isArray(loadedTextures)) {
|
|
1127
|
+
textureArray = loadedTextures;
|
|
1128
|
+
} else if (loadedTextures instanceof three.Texture) {
|
|
1129
|
+
textureArray = [loadedTextures];
|
|
1130
|
+
} else if (IsObject(loadedTextures)) {
|
|
1131
|
+
textureArray = Object.values(loadedTextures);
|
|
1132
|
+
}
|
|
1133
|
+
textureArray.forEach((texture) => {
|
|
1134
|
+
if (texture instanceof three.Texture) {
|
|
1135
|
+
renderer.initTexture(texture);
|
|
1136
|
+
}
|
|
1123
1137
|
});
|
|
1124
1138
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1139
|
+
}, [renderer, loadedTextures, cachedResult]);
|
|
1140
|
+
React.useEffect(() => {
|
|
1141
|
+
if (!cache) return;
|
|
1142
|
+
const urlTextureMap = [];
|
|
1143
|
+
if (typeof stableInput === "string") {
|
|
1144
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1145
|
+
} else if (Array.isArray(stableInput)) {
|
|
1146
|
+
const textureArray = mappedTextures;
|
|
1147
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1148
|
+
} else if (IsObject(stableInput)) {
|
|
1149
|
+
const textureRecord = mappedTextures;
|
|
1150
|
+
for (const key in stableInput) {
|
|
1151
|
+
const url = stableInput[key];
|
|
1152
|
+
urlTextureMap.push([url, textureRecord[key]]);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
store.setState((state) => {
|
|
1156
|
+
const refs = new Map(state._textureRefs);
|
|
1157
|
+
let textures = state.textures;
|
|
1158
|
+
let added = false;
|
|
1159
|
+
for (const [url, texture] of urlTextureMap) {
|
|
1160
|
+
if (!textures.has(url)) {
|
|
1161
|
+
if (!added) {
|
|
1162
|
+
textures = new Map(textures);
|
|
1163
|
+
added = true;
|
|
1164
|
+
}
|
|
1165
|
+
textures.set(url, texture);
|
|
1166
|
+
}
|
|
1167
|
+
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
1168
|
+
}
|
|
1169
|
+
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
1170
|
+
});
|
|
1171
|
+
return () => store.setState((state) => {
|
|
1172
|
+
const refs = new Map(state._textureRefs);
|
|
1173
|
+
for (const [url] of urlTextureMap) {
|
|
1174
|
+
const next = (refs.get(url) ?? 0) - 1;
|
|
1175
|
+
if (next <= 0) refs.delete(url);
|
|
1176
|
+
else refs.set(url, next);
|
|
1177
|
+
}
|
|
1178
|
+
return { _textureRefs: refs };
|
|
1179
|
+
});
|
|
1180
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1181
|
+
return mappedTextures;
|
|
1146
1182
|
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
};
|
|
1158
|
-
useLoader.loader = getLoader$1;
|
|
1159
|
-
|
|
1160
|
-
function useFrame(callback, priorityOrOptions) {
|
|
1161
|
-
const store = React__namespace.useContext(context);
|
|
1162
|
-
const isInsideCanvas = store !== null;
|
|
1163
|
-
const scheduler$1 = scheduler.getScheduler();
|
|
1164
|
-
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
1165
|
-
id: priorityOrOptions.id,
|
|
1166
|
-
phase: priorityOrOptions.phase,
|
|
1167
|
-
priority: priorityOrOptions.priority,
|
|
1168
|
-
fps: priorityOrOptions.fps,
|
|
1169
|
-
drop: priorityOrOptions.drop,
|
|
1170
|
-
enabled: priorityOrOptions.enabled,
|
|
1171
|
-
before: priorityOrOptions.before,
|
|
1172
|
-
after: priorityOrOptions.after
|
|
1173
|
-
}) : "";
|
|
1174
|
-
const options = React__namespace.useMemo(() => {
|
|
1175
|
-
return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
|
|
1176
|
-
}, [optionsKey]);
|
|
1177
|
-
const reactId = React__namespace.useId();
|
|
1178
|
-
const id = options.id ?? reactId;
|
|
1179
|
-
const callbackRef = useMutableCallback(callback);
|
|
1180
|
-
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
1181
|
-
useIsomorphicLayoutEffect(() => {
|
|
1182
|
-
if (!callback) return;
|
|
1183
|
-
if (isInsideCanvas) {
|
|
1184
|
-
const state = store.getState();
|
|
1185
|
-
const rootId = state.internal.rootId;
|
|
1186
|
-
if (isLegacyPriority) {
|
|
1187
|
-
state.internal.priority++;
|
|
1188
|
-
let parentRoot = state.previousRoot;
|
|
1189
|
-
while (parentRoot) {
|
|
1190
|
-
const parentState = parentRoot.getState();
|
|
1191
|
-
if (parentState?.internal) parentState.internal.priority++;
|
|
1192
|
-
parentRoot = parentState?.previousRoot;
|
|
1193
|
-
}
|
|
1194
|
-
notifyDepreciated({
|
|
1195
|
-
heading: "useFrame with numeric priority is deprecated",
|
|
1196
|
-
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 })',
|
|
1197
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1198
|
-
});
|
|
1199
|
-
}
|
|
1200
|
-
const wrappedCallback = (frameState, delta) => {
|
|
1201
|
-
const localState = store.getState();
|
|
1202
|
-
const mergedState = {
|
|
1203
|
-
...localState,
|
|
1204
|
-
time: frameState.time,
|
|
1205
|
-
delta: frameState.delta,
|
|
1206
|
-
elapsed: frameState.elapsed,
|
|
1207
|
-
frame: frameState.frame
|
|
1208
|
-
};
|
|
1209
|
-
callbackRef.current?.(mergedState, delta);
|
|
1210
|
-
};
|
|
1211
|
-
const unregister = scheduler$1.register(wrappedCallback, {
|
|
1212
|
-
id,
|
|
1213
|
-
rootId,
|
|
1214
|
-
...options
|
|
1215
|
-
});
|
|
1216
|
-
return () => {
|
|
1217
|
-
unregister();
|
|
1218
|
-
if (isLegacyPriority) {
|
|
1219
|
-
const currentState = store.getState();
|
|
1220
|
-
if (currentState.internal) {
|
|
1221
|
-
currentState.internal.priority--;
|
|
1222
|
-
let parentRoot = currentState.previousRoot;
|
|
1223
|
-
while (parentRoot) {
|
|
1224
|
-
const parentState = parentRoot.getState();
|
|
1225
|
-
if (parentState?.internal) parentState.internal.priority--;
|
|
1226
|
-
parentRoot = parentState?.previousRoot;
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
};
|
|
1231
|
-
} else {
|
|
1232
|
-
return scheduler$1.register(
|
|
1233
|
-
(state, delta) => {
|
|
1234
|
-
const frameState = state;
|
|
1235
|
-
if (!frameState.renderer) return;
|
|
1236
|
-
callbackRef.current?.(frameState, delta);
|
|
1237
|
-
},
|
|
1238
|
-
{ id, ...options }
|
|
1239
|
-
);
|
|
1240
|
-
}
|
|
1241
|
-
}, [store, scheduler$1, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
1242
|
-
const isPaused = React__namespace.useSyncExternalStore(
|
|
1243
|
-
// Subscribe function
|
|
1244
|
-
React__namespace.useCallback(
|
|
1245
|
-
(onStoreChange) => {
|
|
1246
|
-
return scheduler.getScheduler().subscribeJobState(id, onStoreChange);
|
|
1247
|
-
},
|
|
1248
|
-
[id]
|
|
1249
|
-
),
|
|
1250
|
-
// getSnapshot function
|
|
1251
|
-
React__namespace.useCallback(() => scheduler.getScheduler().isJobPaused(id), [id]),
|
|
1252
|
-
// getServerSnapshot function (SSR)
|
|
1253
|
-
React__namespace.useCallback(() => false, [])
|
|
1254
|
-
);
|
|
1255
|
-
const controls = React__namespace.useMemo(() => {
|
|
1256
|
-
const scheduler2 = scheduler.getScheduler();
|
|
1257
|
-
return {
|
|
1258
|
-
/** The job's unique ID */
|
|
1259
|
-
id,
|
|
1260
|
-
/**
|
|
1261
|
-
* Access to the global scheduler for frame loop control.
|
|
1262
|
-
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1263
|
-
*/
|
|
1264
|
-
scheduler: scheduler2,
|
|
1265
|
-
/**
|
|
1266
|
-
* Manually step this job only.
|
|
1267
|
-
* Bypasses FPS limiting - always runs.
|
|
1268
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1269
|
-
*/
|
|
1270
|
-
step: (timestamp) => {
|
|
1271
|
-
scheduler.getScheduler().stepJob(id, timestamp);
|
|
1272
|
-
},
|
|
1273
|
-
/**
|
|
1274
|
-
* Manually step ALL jobs in the scheduler.
|
|
1275
|
-
* Useful for frameloop='never' mode.
|
|
1276
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1277
|
-
*/
|
|
1278
|
-
stepAll: (timestamp) => {
|
|
1279
|
-
scheduler.getScheduler().step(timestamp);
|
|
1280
|
-
},
|
|
1281
|
-
/**
|
|
1282
|
-
* Pause this job (set enabled=false).
|
|
1283
|
-
* Job remains registered but won't run.
|
|
1284
|
-
*/
|
|
1285
|
-
pause: () => {
|
|
1286
|
-
scheduler.getScheduler().pauseJob(id);
|
|
1287
|
-
},
|
|
1288
|
-
/**
|
|
1289
|
-
* Resume this job (set enabled=true).
|
|
1290
|
-
*/
|
|
1291
|
-
resume: () => {
|
|
1292
|
-
scheduler.getScheduler().resumeJob(id);
|
|
1293
|
-
},
|
|
1294
|
-
/**
|
|
1295
|
-
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1296
|
-
* No need for forceUpdate() in your components.
|
|
1297
|
-
*/
|
|
1298
|
-
isPaused
|
|
1299
|
-
};
|
|
1300
|
-
}, [id, isPaused]);
|
|
1301
|
-
return controls;
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1305
|
-
function getUrls(input) {
|
|
1306
|
-
if (typeof input === "string") return [input];
|
|
1307
|
-
if (Array.isArray(input)) return input;
|
|
1308
|
-
return Object.values(input);
|
|
1309
|
-
}
|
|
1310
|
-
function allUrlsCached(urls, textureCache) {
|
|
1311
|
-
return urls.every((url) => textureCache.has(url));
|
|
1312
|
-
}
|
|
1313
|
-
function buildFromCache(input, textureCache) {
|
|
1314
|
-
if (typeof input === "string") {
|
|
1315
|
-
return textureCache.get(input);
|
|
1316
|
-
} else if (Array.isArray(input)) {
|
|
1317
|
-
return input.map((url) => textureCache.get(url));
|
|
1318
|
-
} else {
|
|
1319
|
-
const result = {};
|
|
1320
|
-
const objInput = input;
|
|
1321
|
-
for (const key in objInput) {
|
|
1322
|
-
result[key] = textureCache.get(objInput[key]);
|
|
1323
|
-
}
|
|
1324
|
-
return result;
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
function useTexture(input, optionsOrOnLoad) {
|
|
1328
|
-
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1329
|
-
const store = useStore();
|
|
1330
|
-
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1331
|
-
const { onLoad, cache = true } = options;
|
|
1332
|
-
const onLoadRef = React.useRef(onLoad);
|
|
1333
|
-
onLoadRef.current = onLoad;
|
|
1334
|
-
const onLoadCalledForRef = React.useRef(null);
|
|
1335
|
-
const urls = React.useMemo(() => getUrls(input), [input]);
|
|
1336
|
-
const cachedResult = React.useMemo(() => {
|
|
1337
|
-
if (!cache) return null;
|
|
1338
|
-
const textures = store.getState().textures;
|
|
1339
|
-
if (!allUrlsCached(urls, textures)) return null;
|
|
1340
|
-
return buildFromCache(input, textures);
|
|
1341
|
-
}, [cache, urls, input, store]);
|
|
1342
|
-
const loadedTextures = useLoader(
|
|
1343
|
-
three.TextureLoader,
|
|
1344
|
-
IsObject(input) ? Object.values(input) : input
|
|
1345
|
-
);
|
|
1346
|
-
const inputKey = urls.join("\0");
|
|
1347
|
-
React.useLayoutEffect(() => {
|
|
1348
|
-
if (cachedResult) return;
|
|
1349
|
-
if (onLoadCalledForRef.current === inputKey) return;
|
|
1350
|
-
onLoadCalledForRef.current = inputKey;
|
|
1351
|
-
onLoadRef.current?.(loadedTextures);
|
|
1352
|
-
}, [cachedResult, loadedTextures, inputKey]);
|
|
1353
|
-
React.useEffect(() => {
|
|
1354
|
-
if (cachedResult) return;
|
|
1355
|
-
if ("initTexture" in renderer) {
|
|
1356
|
-
let textureArray = [];
|
|
1357
|
-
if (Array.isArray(loadedTextures)) {
|
|
1358
|
-
textureArray = loadedTextures;
|
|
1359
|
-
} else if (loadedTextures instanceof three.Texture) {
|
|
1360
|
-
textureArray = [loadedTextures];
|
|
1361
|
-
} else if (IsObject(loadedTextures)) {
|
|
1362
|
-
textureArray = Object.values(loadedTextures);
|
|
1363
|
-
}
|
|
1364
|
-
textureArray.forEach((texture) => {
|
|
1365
|
-
if (texture instanceof three.Texture) {
|
|
1366
|
-
renderer.initTexture(texture);
|
|
1367
|
-
}
|
|
1368
|
-
});
|
|
1369
|
-
}
|
|
1370
|
-
}, [renderer, loadedTextures, cachedResult]);
|
|
1371
|
-
const mappedTextures = React.useMemo(() => {
|
|
1372
|
-
if (cachedResult) return cachedResult;
|
|
1373
|
-
if (IsObject(input)) {
|
|
1374
|
-
const keyed = {};
|
|
1375
|
-
const textureArray = loadedTextures;
|
|
1376
|
-
let i = 0;
|
|
1377
|
-
for (const key in input) keyed[key] = textureArray[i++];
|
|
1378
|
-
return keyed;
|
|
1379
|
-
} else {
|
|
1380
|
-
return loadedTextures;
|
|
1381
|
-
}
|
|
1382
|
-
}, [input, loadedTextures, cachedResult]);
|
|
1383
|
-
React.useEffect(() => {
|
|
1384
|
-
if (!cache) return;
|
|
1385
|
-
const urlTextureMap = [];
|
|
1386
|
-
if (typeof input === "string") {
|
|
1387
|
-
urlTextureMap.push([input, mappedTextures]);
|
|
1388
|
-
} else if (Array.isArray(input)) {
|
|
1389
|
-
const textureArray = mappedTextures;
|
|
1390
|
-
input.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1391
|
-
} else if (IsObject(input)) {
|
|
1392
|
-
const textureRecord = mappedTextures;
|
|
1393
|
-
for (const key in input) {
|
|
1394
|
-
const url = input[key];
|
|
1395
|
-
urlTextureMap.push([url, textureRecord[key]]);
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
store.setState((state) => {
|
|
1399
|
-
const refs = new Map(state._textureRefs);
|
|
1400
|
-
let textures = state.textures;
|
|
1401
|
-
let added = false;
|
|
1402
|
-
for (const [url, texture] of urlTextureMap) {
|
|
1403
|
-
if (!textures.has(url)) {
|
|
1404
|
-
if (!added) {
|
|
1405
|
-
textures = new Map(textures);
|
|
1406
|
-
added = true;
|
|
1407
|
-
}
|
|
1408
|
-
textures.set(url, texture);
|
|
1409
|
-
}
|
|
1410
|
-
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
1411
|
-
}
|
|
1412
|
-
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
1413
|
-
});
|
|
1414
|
-
return () => store.setState((state) => {
|
|
1415
|
-
const refs = new Map(state._textureRefs);
|
|
1416
|
-
for (const [url] of urlTextureMap) {
|
|
1417
|
-
const next = (refs.get(url) ?? 0) - 1;
|
|
1418
|
-
if (next <= 0) refs.delete(url);
|
|
1419
|
-
else refs.set(url, next);
|
|
1420
|
-
}
|
|
1421
|
-
return { _textureRefs: refs };
|
|
1422
|
-
});
|
|
1423
|
-
}, [cache, input, mappedTextures, store]);
|
|
1424
|
-
return mappedTextures;
|
|
1425
|
-
}
|
|
1426
|
-
useTexture.preload = (url) => useLoader.preload(three.TextureLoader, url);
|
|
1427
|
-
useTexture.clear = (input) => useLoader.clear(three.TextureLoader, input);
|
|
1428
|
-
const Texture = ({
|
|
1429
|
-
children,
|
|
1430
|
-
input,
|
|
1431
|
-
onLoad,
|
|
1432
|
-
cache
|
|
1433
|
-
}) => {
|
|
1434
|
-
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1435
|
-
const ret = useTexture(input, options);
|
|
1436
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children?.(ret) });
|
|
1183
|
+
useTexture.preload = (url) => useLoader.preload(three.TextureLoader, url);
|
|
1184
|
+
useTexture.clear = (input) => useLoader.clear(three.TextureLoader, input);
|
|
1185
|
+
const Texture = ({
|
|
1186
|
+
children,
|
|
1187
|
+
input,
|
|
1188
|
+
onLoad,
|
|
1189
|
+
cache
|
|
1190
|
+
}) => {
|
|
1191
|
+
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1192
|
+
const ret = useTexture(input, options);
|
|
1193
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children?.(ret) });
|
|
1437
1194
|
};
|
|
1438
1195
|
|
|
1439
1196
|
function useTextures(selector) {
|
|
@@ -1491,13 +1248,13 @@ function useTextures(selector) {
|
|
|
1491
1248
|
};
|
|
1492
1249
|
}, [store]);
|
|
1493
1250
|
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
1494
|
-
const selected = useThree(subscribe);
|
|
1251
|
+
const selected = useThree$1(subscribe);
|
|
1495
1252
|
return selector ? selected : registry;
|
|
1496
1253
|
}
|
|
1497
1254
|
|
|
1498
1255
|
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
1499
|
-
const isLegacy = useThree((s) => s.isLegacy);
|
|
1500
|
-
const size = useThree((s) => s.size);
|
|
1256
|
+
const isLegacy = useThree$1((s) => s.isLegacy);
|
|
1257
|
+
const size = useThree$1((s) => s.size);
|
|
1501
1258
|
let width;
|
|
1502
1259
|
let height;
|
|
1503
1260
|
let opts;
|
|
@@ -1554,7 +1311,7 @@ function useEnvironment({
|
|
|
1554
1311
|
const { extension, isCubemap } = getExtension(files);
|
|
1555
1312
|
const loader = getLoader(extension);
|
|
1556
1313
|
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1557
|
-
const renderer = useThree((state) => state.renderer);
|
|
1314
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
1558
1315
|
React.useLayoutEffect(() => {
|
|
1559
1316
|
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
1560
1317
|
function clearGainmapTexture() {
|
|
@@ -1581,7 +1338,7 @@ function useEnvironment({
|
|
|
1581
1338
|
texture = texture.renderTarget?.texture;
|
|
1582
1339
|
}
|
|
1583
1340
|
texture.mapping = isCubemap ? three.CubeReflectionMapping : three.EquirectangularReflectionMapping;
|
|
1584
|
-
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
1341
|
+
texture.colorSpace = colorSpace ?? (isCubemap && extension !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
1585
1342
|
return texture;
|
|
1586
1343
|
}
|
|
1587
1344
|
const preloadDefaultOptions = {
|
|
@@ -1634,22 +1391,15 @@ function getExtension(files) {
|
|
|
1634
1391
|
const isCubemap = isArray(files) && files.length === 6;
|
|
1635
1392
|
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
1636
1393
|
const firstEntry = isArray(files) ? files[0] : files;
|
|
1637
|
-
const
|
|
1394
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1395
|
+
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;
|
|
1638
1396
|
return { extension, isCubemap, isGainmap };
|
|
1639
1397
|
}
|
|
1640
1398
|
function getLoader(extension) {
|
|
1641
|
-
const loader = extension === "cube" ? three.CubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
|
|
1399
|
+
const loader = extension === "cube" ? three.CubeTextureLoader : extension === "hdr-cube" ? HDRCubeTextureLoader_js.HDRCubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
|
|
1642
1400
|
return loader;
|
|
1643
1401
|
}
|
|
1644
1402
|
|
|
1645
|
-
function useStore() {
|
|
1646
|
-
const store = React.useContext(context);
|
|
1647
|
-
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1648
|
-
return store;
|
|
1649
|
-
}
|
|
1650
|
-
function useThree(selector = (state) => state, equalityFn) {
|
|
1651
|
-
return useStore()(selector, equalityFn);
|
|
1652
|
-
}
|
|
1653
1403
|
function useInstanceHandle(ref) {
|
|
1654
1404
|
const instance = React.useRef(null);
|
|
1655
1405
|
React.useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
@@ -1689,13 +1439,19 @@ function addTail(callback) {
|
|
|
1689
1439
|
return scheduler.getScheduler().onIdle(callback);
|
|
1690
1440
|
}
|
|
1691
1441
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1692
|
-
|
|
1442
|
+
const rootId = state?.internal?.rootId;
|
|
1443
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1444
|
+
if (rootId) scheduler$1.invalidateRoot(rootId, frames, stackFrames);
|
|
1445
|
+
else scheduler$1.invalidate(frames, stackFrames);
|
|
1693
1446
|
}
|
|
1694
|
-
function advance(timestamp) {
|
|
1695
|
-
|
|
1447
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1448
|
+
const rootId = state?.internal?.rootId;
|
|
1449
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1450
|
+
if (rootId) scheduler$1.stepRoot(rootId, timestamp);
|
|
1451
|
+
else scheduler$1.step(timestamp);
|
|
1696
1452
|
}
|
|
1697
1453
|
|
|
1698
|
-
const version = "10.0.0-alpha.
|
|
1454
|
+
const version = "10.0.0-alpha.5";
|
|
1699
1455
|
const packageData = {
|
|
1700
1456
|
version: version};
|
|
1701
1457
|
|
|
@@ -13554,7 +13310,10 @@ function extend(objects) {
|
|
|
13554
13310
|
catalogue[Component] = objects;
|
|
13555
13311
|
return Component;
|
|
13556
13312
|
} else {
|
|
13557
|
-
|
|
13313
|
+
for (const name in objects) {
|
|
13314
|
+
const object = objects[name];
|
|
13315
|
+
if (isConstructor(object)) catalogue[name] = object;
|
|
13316
|
+
}
|
|
13558
13317
|
}
|
|
13559
13318
|
}
|
|
13560
13319
|
function validateInstance(type, props) {
|
|
@@ -13902,7 +13661,7 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13902
13661
|
getRootHostContext: () => NO_CONTEXT,
|
|
13903
13662
|
getChildHostContext: () => NO_CONTEXT,
|
|
13904
13663
|
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
13905
|
-
validateInstance(type, newProps);
|
|
13664
|
+
validateInstance(instance.type, newProps);
|
|
13906
13665
|
let reconstruct = false;
|
|
13907
13666
|
if (instance.type === "primitive" && oldProps.object !== newProps.object) reconstruct = true;
|
|
13908
13667
|
else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
|
|
@@ -13917,162 +13676,491 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13917
13676
|
else delete instance.props.attach;
|
|
13918
13677
|
if (Object.keys(changedProps).length) applyProps(instance.object, changedProps);
|
|
13919
13678
|
}
|
|
13920
|
-
},
|
|
13921
|
-
finalizeInitialChildren: (instance) => {
|
|
13922
|
-
for (const prop in instance.props) {
|
|
13923
|
-
if (isFromRef(instance.props[prop])) return true;
|
|
13679
|
+
},
|
|
13680
|
+
finalizeInitialChildren: (instance) => {
|
|
13681
|
+
for (const prop in instance.props) {
|
|
13682
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
13683
|
+
}
|
|
13684
|
+
return false;
|
|
13685
|
+
},
|
|
13686
|
+
commitMount(instance) {
|
|
13687
|
+
const resolved = {};
|
|
13688
|
+
for (const prop in instance.props) {
|
|
13689
|
+
const value = instance.props[prop];
|
|
13690
|
+
if (isFromRef(value)) {
|
|
13691
|
+
const { [FROM_REF]: ref, transform } = value;
|
|
13692
|
+
if (ref.current != null) resolved[prop] = transform ? transform(ref.current) : ref.current;
|
|
13693
|
+
}
|
|
13694
|
+
}
|
|
13695
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
13696
|
+
},
|
|
13697
|
+
getPublicInstance: (instance) => instance?.object,
|
|
13698
|
+
prepareForCommit: () => null,
|
|
13699
|
+
preparePortalMount: (container) => {
|
|
13700
|
+
const target = container.getState().internal.container ?? container.getState().scene;
|
|
13701
|
+
return prepare(target, container, "", {});
|
|
13702
|
+
},
|
|
13703
|
+
// Reconstructed instances are swapped once all mutations are committed,
|
|
13704
|
+
// before layout effects run so refs point to the new objects
|
|
13705
|
+
resetAfterCommit: flushReconstructedInstances,
|
|
13706
|
+
shouldSetTextContent: () => false,
|
|
13707
|
+
clearContainer: () => false,
|
|
13708
|
+
hideInstance,
|
|
13709
|
+
unhideInstance,
|
|
13710
|
+
createTextInstance: handleTextInstance,
|
|
13711
|
+
hideTextInstance: handleTextInstance,
|
|
13712
|
+
unhideTextInstance: handleTextInstance,
|
|
13713
|
+
// Mirrors react-dom, which flushes discrete work in microtasks
|
|
13714
|
+
supportsMicrotasks: true,
|
|
13715
|
+
scheduleMicrotask,
|
|
13716
|
+
scheduleTimeout: typeof setTimeout === "function" ? setTimeout : void 0,
|
|
13717
|
+
cancelTimeout: typeof clearTimeout === "function" ? clearTimeout : void 0,
|
|
13718
|
+
noTimeout: -1,
|
|
13719
|
+
getInstanceFromNode: () => null,
|
|
13720
|
+
beforeActiveInstanceBlur() {
|
|
13721
|
+
},
|
|
13722
|
+
afterActiveInstanceBlur() {
|
|
13723
|
+
},
|
|
13724
|
+
detachDeletedInstance() {
|
|
13725
|
+
},
|
|
13726
|
+
prepareScopeUpdate() {
|
|
13727
|
+
},
|
|
13728
|
+
getInstanceFromScope: () => null,
|
|
13729
|
+
shouldAttemptEagerTransition: () => false,
|
|
13730
|
+
trackSchedulerEvent: () => {
|
|
13731
|
+
},
|
|
13732
|
+
resolveEventType: () => null,
|
|
13733
|
+
resolveEventTimeStamp: () => -1.1,
|
|
13734
|
+
requestPostPaintCallback() {
|
|
13735
|
+
},
|
|
13736
|
+
maySuspendCommit: () => false,
|
|
13737
|
+
preloadInstance: () => true,
|
|
13738
|
+
// true indicates already loaded
|
|
13739
|
+
suspendInstance() {
|
|
13740
|
+
},
|
|
13741
|
+
waitForCommitToBeReady: () => null,
|
|
13742
|
+
NotPendingTransition: null,
|
|
13743
|
+
// The reconciler types use the internal ReactContext with all the hidden properties
|
|
13744
|
+
// so we have to cast from the public React.Context type
|
|
13745
|
+
HostTransitionContext: /* @__PURE__ */ React__namespace.createContext(
|
|
13746
|
+
null
|
|
13747
|
+
),
|
|
13748
|
+
setCurrentUpdatePriority(newPriority) {
|
|
13749
|
+
currentUpdatePriority = newPriority;
|
|
13750
|
+
},
|
|
13751
|
+
getCurrentUpdatePriority() {
|
|
13752
|
+
return currentUpdatePriority;
|
|
13753
|
+
},
|
|
13754
|
+
resolveUpdatePriority() {
|
|
13755
|
+
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13756
|
+
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13757
|
+
if (eventType === void 0) return r;
|
|
13758
|
+
return getEventPriority(eventType);
|
|
13759
|
+
},
|
|
13760
|
+
resetFormInstance() {
|
|
13761
|
+
},
|
|
13762
|
+
// @ts-ignore DefinitelyTyped is not up to date
|
|
13763
|
+
rendererPackageName: "@react-three/fiber",
|
|
13764
|
+
rendererVersion: packageData.version,
|
|
13765
|
+
// 19.2 Reconciler
|
|
13766
|
+
// https://github.com/facebook/react/pull/31975
|
|
13767
|
+
// https://github.com/facebook/react/pull/31999
|
|
13768
|
+
applyViewTransitionName(_instance, _name, _className) {
|
|
13769
|
+
},
|
|
13770
|
+
restoreViewTransitionName(_instance, _props) {
|
|
13771
|
+
},
|
|
13772
|
+
cancelViewTransitionName(_instance, _name, _props) {
|
|
13773
|
+
},
|
|
13774
|
+
cancelRootViewTransitionName(_rootContainer) {
|
|
13775
|
+
},
|
|
13776
|
+
restoreRootViewTransitionName(_rootContainer) {
|
|
13777
|
+
},
|
|
13778
|
+
InstanceMeasurement: null,
|
|
13779
|
+
measureInstance: (_instance) => null,
|
|
13780
|
+
wasInstanceInViewport: (_measurement) => true,
|
|
13781
|
+
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
13782
|
+
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
13783
|
+
// https://github.com/facebook/react/pull/32002
|
|
13784
|
+
// https://github.com/facebook/react/pull/34486
|
|
13785
|
+
suspendOnActiveViewTransition(_state, _container) {
|
|
13786
|
+
},
|
|
13787
|
+
// https://github.com/facebook/react/pull/32451
|
|
13788
|
+
// https://github.com/facebook/react/pull/32760
|
|
13789
|
+
startGestureTransition: () => null,
|
|
13790
|
+
startViewTransition: () => null,
|
|
13791
|
+
stopViewTransition(_transition) {
|
|
13792
|
+
},
|
|
13793
|
+
// https://github.com/facebook/react/pull/32038
|
|
13794
|
+
createViewTransitionInstance: (_name) => null,
|
|
13795
|
+
// https://github.com/facebook/react/pull/32379
|
|
13796
|
+
// https://github.com/facebook/react/pull/32786
|
|
13797
|
+
getCurrentGestureOffset(_provider) {
|
|
13798
|
+
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
13799
|
+
},
|
|
13800
|
+
// https://github.com/facebook/react/pull/32500
|
|
13801
|
+
cloneMutableInstance(instance, _keepChildren) {
|
|
13802
|
+
return instance;
|
|
13803
|
+
},
|
|
13804
|
+
cloneMutableTextInstance(textInstance) {
|
|
13805
|
+
return textInstance;
|
|
13806
|
+
},
|
|
13807
|
+
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
13808
|
+
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
13809
|
+
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
13810
|
+
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
13811
|
+
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
13812
|
+
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
13813
|
+
cloneRootViewTransitionContainer(_rootContainer) {
|
|
13814
|
+
},
|
|
13815
|
+
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
13816
|
+
},
|
|
13817
|
+
// https://github.com/facebook/react/pull/32465
|
|
13818
|
+
createFragmentInstance: (_fiber) => null,
|
|
13819
|
+
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
13820
|
+
},
|
|
13821
|
+
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
13822
|
+
},
|
|
13823
|
+
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
13824
|
+
},
|
|
13825
|
+
// https://github.com/facebook/react/pull/32653
|
|
13826
|
+
measureClonedInstance: (_instance) => null,
|
|
13827
|
+
// https://github.com/facebook/react/pull/32819
|
|
13828
|
+
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
13829
|
+
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
13830
|
+
// https://github.com/facebook/react/pull/34486
|
|
13831
|
+
startSuspendingCommit: () => null,
|
|
13832
|
+
// https://github.com/facebook/react/pull/34522
|
|
13833
|
+
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
13834
|
+
});
|
|
13835
|
+
|
|
13836
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
13837
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
13838
|
+
if (!stack) return false;
|
|
13839
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
13840
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
13841
|
+
}
|
|
13842
|
+
|
|
13843
|
+
const createStore = (invalidate, advance) => {
|
|
13844
|
+
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
13845
|
+
const position = new three.Vector3();
|
|
13846
|
+
const defaultTarget = new three.Vector3();
|
|
13847
|
+
const tempTarget = new three.Vector3();
|
|
13848
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
13849
|
+
const { width, height, top, left } = size;
|
|
13850
|
+
const aspect = width / height;
|
|
13851
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
13852
|
+
else tempTarget.set(...target);
|
|
13853
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
13854
|
+
if (isOrthographicCamera(camera)) {
|
|
13855
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
13856
|
+
} else {
|
|
13857
|
+
const fov = camera.fov * Math.PI / 180;
|
|
13858
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
13859
|
+
const w = h * (width / height);
|
|
13860
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
13861
|
+
}
|
|
13862
|
+
}
|
|
13863
|
+
let performanceTimeout = void 0;
|
|
13864
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
13865
|
+
const pointer = new three.Vector2();
|
|
13866
|
+
const rootState = {
|
|
13867
|
+
set,
|
|
13868
|
+
get,
|
|
13869
|
+
// Mock objects that have to be configured
|
|
13870
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
13871
|
+
primaryStore: null,
|
|
13872
|
+
gl: null,
|
|
13873
|
+
renderer: null,
|
|
13874
|
+
camera: null,
|
|
13875
|
+
frustum: new three.Frustum(),
|
|
13876
|
+
autoUpdateFrustum: true,
|
|
13877
|
+
raycaster: null,
|
|
13878
|
+
events: {
|
|
13879
|
+
priority: 1,
|
|
13880
|
+
enabled: true,
|
|
13881
|
+
connected: false,
|
|
13882
|
+
frameTimedRaycasts: true,
|
|
13883
|
+
alwaysFireOnScroll: true,
|
|
13884
|
+
updateOnFrame: false
|
|
13885
|
+
},
|
|
13886
|
+
scene: null,
|
|
13887
|
+
rootScene: null,
|
|
13888
|
+
xr: null,
|
|
13889
|
+
inspector: null,
|
|
13890
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
13891
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
13892
|
+
textureColorSpace: three.SRGBColorSpace,
|
|
13893
|
+
isLegacy: false,
|
|
13894
|
+
webGPUSupported: false,
|
|
13895
|
+
isNative: false,
|
|
13896
|
+
controls: null,
|
|
13897
|
+
pointer,
|
|
13898
|
+
mouse: pointer,
|
|
13899
|
+
frameloop: "always",
|
|
13900
|
+
onPointerMissed: void 0,
|
|
13901
|
+
onDragOverMissed: void 0,
|
|
13902
|
+
onDropMissed: void 0,
|
|
13903
|
+
performance: {
|
|
13904
|
+
current: 1,
|
|
13905
|
+
min: 0.5,
|
|
13906
|
+
max: 1,
|
|
13907
|
+
debounce: 200,
|
|
13908
|
+
regress: () => {
|
|
13909
|
+
const state2 = get();
|
|
13910
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
13911
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
13912
|
+
performanceTimeout = setTimeout(
|
|
13913
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
13914
|
+
state2.performance.debounce
|
|
13915
|
+
);
|
|
13916
|
+
}
|
|
13917
|
+
},
|
|
13918
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
13919
|
+
viewport: {
|
|
13920
|
+
initialDpr: 0,
|
|
13921
|
+
dpr: 0,
|
|
13922
|
+
width: 0,
|
|
13923
|
+
height: 0,
|
|
13924
|
+
top: 0,
|
|
13925
|
+
left: 0,
|
|
13926
|
+
aspect: 0,
|
|
13927
|
+
distance: 0,
|
|
13928
|
+
factor: 0,
|
|
13929
|
+
getCurrentViewport
|
|
13930
|
+
},
|
|
13931
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
13932
|
+
setSize: (width, height, top, left) => {
|
|
13933
|
+
const state2 = get();
|
|
13934
|
+
if (width === void 0) {
|
|
13935
|
+
set({ _sizeImperative: false });
|
|
13936
|
+
if (state2._sizeProps) {
|
|
13937
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
13938
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
13939
|
+
const currentSize = state2.size;
|
|
13940
|
+
const newSize = {
|
|
13941
|
+
width: propW ?? currentSize.width,
|
|
13942
|
+
height: propH ?? currentSize.height,
|
|
13943
|
+
top: currentSize.top,
|
|
13944
|
+
left: currentSize.left
|
|
13945
|
+
};
|
|
13946
|
+
set((s) => ({
|
|
13947
|
+
size: newSize,
|
|
13948
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
13949
|
+
}));
|
|
13950
|
+
get().invalidate();
|
|
13951
|
+
}
|
|
13952
|
+
}
|
|
13953
|
+
return;
|
|
13954
|
+
}
|
|
13955
|
+
const w = width;
|
|
13956
|
+
const h = height ?? width;
|
|
13957
|
+
const t = top ?? state2.size.top;
|
|
13958
|
+
const l = left ?? state2.size.left;
|
|
13959
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
13960
|
+
set((s) => ({
|
|
13961
|
+
size,
|
|
13962
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
13963
|
+
_sizeImperative: true
|
|
13964
|
+
}));
|
|
13965
|
+
get().invalidate();
|
|
13966
|
+
},
|
|
13967
|
+
setDpr: (dpr) => set((state2) => {
|
|
13968
|
+
const resolved = calculateDpr(dpr);
|
|
13969
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
13970
|
+
}),
|
|
13971
|
+
setFrameloop: (frameloop = "always") => {
|
|
13972
|
+
const rootId = get().internal.rootId;
|
|
13973
|
+
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
13974
|
+
set(() => ({ frameloop }));
|
|
13975
|
+
},
|
|
13976
|
+
setError: (error) => set(() => ({ error })),
|
|
13977
|
+
error: null,
|
|
13978
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
13979
|
+
uniforms: {},
|
|
13980
|
+
nodes: {},
|
|
13981
|
+
buffers: {},
|
|
13982
|
+
gpuStorage: {},
|
|
13983
|
+
textures: /* @__PURE__ */ new Map(),
|
|
13984
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
13985
|
+
renderPipeline: null,
|
|
13986
|
+
passes: {},
|
|
13987
|
+
_hmrVersion: 0,
|
|
13988
|
+
_sizeImperative: false,
|
|
13989
|
+
_sizeProps: null,
|
|
13990
|
+
previousRoot: void 0,
|
|
13991
|
+
internal: {
|
|
13992
|
+
// Events
|
|
13993
|
+
interaction: [],
|
|
13994
|
+
subscribers: [],
|
|
13995
|
+
// Per-pointer state (new unified structure)
|
|
13996
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
13997
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
13998
|
+
lastEvent: React__namespace.createRef(),
|
|
13999
|
+
// Deprecated but kept for backwards compatibility
|
|
14000
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
14001
|
+
initialClick: [0, 0],
|
|
14002
|
+
initialHits: [],
|
|
14003
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
14004
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
14005
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
14006
|
+
// Occlusion system (WebGPU only)
|
|
14007
|
+
occlusionEnabled: false,
|
|
14008
|
+
occlusionObserver: null,
|
|
14009
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
14010
|
+
helperGroup: null,
|
|
14011
|
+
// Updates
|
|
14012
|
+
active: false,
|
|
14013
|
+
frames: 0,
|
|
14014
|
+
priority: 0,
|
|
14015
|
+
subscribe: (ref, priority, store) => {
|
|
14016
|
+
const internal = get().internal;
|
|
14017
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
14018
|
+
internal.subscribers.push({ ref, priority, store });
|
|
14019
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14020
|
+
return () => {
|
|
14021
|
+
const internal2 = get().internal;
|
|
14022
|
+
if (internal2?.subscribers) {
|
|
14023
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14024
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14025
|
+
}
|
|
14026
|
+
};
|
|
14027
|
+
},
|
|
14028
|
+
// Renderer Storage (single source of truth)
|
|
14029
|
+
actualRenderer: null,
|
|
14030
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14031
|
+
scheduler: null,
|
|
14032
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
14033
|
+
renderOverride: null
|
|
14034
|
+
}
|
|
14035
|
+
};
|
|
14036
|
+
return rootState;
|
|
14037
|
+
});
|
|
14038
|
+
const state = rootStore.getState();
|
|
14039
|
+
Object.defineProperty(state, "gl", {
|
|
14040
|
+
get() {
|
|
14041
|
+
const currentState = rootStore.getState();
|
|
14042
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14043
|
+
const stack = new Error().stack || "";
|
|
14044
|
+
if (!isInternalRendererAccess(stack)) {
|
|
14045
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14046
|
+
notifyDepreciated({
|
|
14047
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
14048
|
+
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
|
|
14049
|
+
});
|
|
14050
|
+
}
|
|
14051
|
+
}
|
|
14052
|
+
return currentState.internal.actualRenderer;
|
|
14053
|
+
},
|
|
14054
|
+
set(value) {
|
|
14055
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14056
|
+
},
|
|
14057
|
+
enumerable: true,
|
|
14058
|
+
configurable: true
|
|
14059
|
+
});
|
|
14060
|
+
Object.defineProperty(state, "renderer", {
|
|
14061
|
+
get() {
|
|
14062
|
+
return rootStore.getState().internal.actualRenderer;
|
|
14063
|
+
},
|
|
14064
|
+
set(value) {
|
|
14065
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14066
|
+
},
|
|
14067
|
+
enumerable: true,
|
|
14068
|
+
configurable: true
|
|
14069
|
+
});
|
|
14070
|
+
let oldScene = state.scene;
|
|
14071
|
+
rootStore.subscribe(() => {
|
|
14072
|
+
const currentState = rootStore.getState();
|
|
14073
|
+
const { scene, rootScene, set } = currentState;
|
|
14074
|
+
if (scene !== oldScene) {
|
|
14075
|
+
oldScene = scene;
|
|
14076
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
14077
|
+
set({ rootScene: scene });
|
|
14078
|
+
}
|
|
14079
|
+
}
|
|
14080
|
+
});
|
|
14081
|
+
let oldSize = state.size;
|
|
14082
|
+
let oldDpr = state.viewport.dpr;
|
|
14083
|
+
let oldCamera = state.camera;
|
|
14084
|
+
rootStore.subscribe(() => {
|
|
14085
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14086
|
+
const actualRenderer = internal.actualRenderer;
|
|
14087
|
+
const canvasTarget = internal.canvasTarget;
|
|
14088
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14089
|
+
oldSize = size;
|
|
14090
|
+
oldDpr = viewport.dpr;
|
|
14091
|
+
updateCamera(camera, size);
|
|
14092
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14093
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14094
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
14095
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14096
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
13924
14097
|
}
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
14098
|
+
if (camera !== oldCamera) {
|
|
14099
|
+
oldCamera = camera;
|
|
14100
|
+
const { rootScene } = rootStore.getState();
|
|
14101
|
+
if (camera && rootScene && !camera.parent) {
|
|
14102
|
+
rootScene.add(camera);
|
|
14103
|
+
}
|
|
14104
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14105
|
+
const currentState = rootStore.getState();
|
|
14106
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
14107
|
+
updateFrustum(camera, currentState.frustum);
|
|
13934
14108
|
}
|
|
13935
14109
|
}
|
|
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
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
),
|
|
13989
|
-
|
|
13990
|
-
currentUpdatePriority = newPriority;
|
|
13991
|
-
},
|
|
13992
|
-
getCurrentUpdatePriority() {
|
|
13993
|
-
return currentUpdatePriority;
|
|
13994
|
-
},
|
|
13995
|
-
resolveUpdatePriority() {
|
|
13996
|
-
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13997
|
-
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13998
|
-
if (eventType === void 0) return r;
|
|
13999
|
-
return getEventPriority(eventType);
|
|
14000
|
-
},
|
|
14001
|
-
resetFormInstance() {
|
|
14002
|
-
},
|
|
14003
|
-
// @ts-ignore DefinitelyTyped is not up to date
|
|
14004
|
-
rendererPackageName: "@react-three/fiber",
|
|
14005
|
-
rendererVersion: packageData.version,
|
|
14006
|
-
// 19.2 Reconciler
|
|
14007
|
-
// https://github.com/facebook/react/pull/31975
|
|
14008
|
-
// https://github.com/facebook/react/pull/31999
|
|
14009
|
-
applyViewTransitionName(_instance, _name, _className) {
|
|
14010
|
-
},
|
|
14011
|
-
restoreViewTransitionName(_instance, _props) {
|
|
14012
|
-
},
|
|
14013
|
-
cancelViewTransitionName(_instance, _name, _props) {
|
|
14014
|
-
},
|
|
14015
|
-
cancelRootViewTransitionName(_rootContainer) {
|
|
14016
|
-
},
|
|
14017
|
-
restoreRootViewTransitionName(_rootContainer) {
|
|
14018
|
-
},
|
|
14019
|
-
InstanceMeasurement: null,
|
|
14020
|
-
measureInstance: (_instance) => null,
|
|
14021
|
-
wasInstanceInViewport: (_measurement) => true,
|
|
14022
|
-
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
14023
|
-
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
14024
|
-
// https://github.com/facebook/react/pull/32002
|
|
14025
|
-
// https://github.com/facebook/react/pull/34486
|
|
14026
|
-
suspendOnActiveViewTransition(_state, _container) {
|
|
14027
|
-
},
|
|
14028
|
-
// https://github.com/facebook/react/pull/32451
|
|
14029
|
-
// https://github.com/facebook/react/pull/32760
|
|
14030
|
-
startGestureTransition: () => null,
|
|
14031
|
-
startViewTransition: () => null,
|
|
14032
|
-
stopViewTransition(_transition) {
|
|
14033
|
-
},
|
|
14034
|
-
// https://github.com/facebook/react/pull/32038
|
|
14035
|
-
createViewTransitionInstance: (_name) => null,
|
|
14036
|
-
// https://github.com/facebook/react/pull/32379
|
|
14037
|
-
// https://github.com/facebook/react/pull/32786
|
|
14038
|
-
getCurrentGestureOffset(_provider) {
|
|
14039
|
-
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
14040
|
-
},
|
|
14041
|
-
// https://github.com/facebook/react/pull/32500
|
|
14042
|
-
cloneMutableInstance(instance, _keepChildren) {
|
|
14043
|
-
return instance;
|
|
14044
|
-
},
|
|
14045
|
-
cloneMutableTextInstance(textInstance) {
|
|
14046
|
-
return textInstance;
|
|
14047
|
-
},
|
|
14048
|
-
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
14049
|
-
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
14050
|
-
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
14051
|
-
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
14052
|
-
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
14053
|
-
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
14054
|
-
cloneRootViewTransitionContainer(_rootContainer) {
|
|
14055
|
-
},
|
|
14056
|
-
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
14057
|
-
},
|
|
14058
|
-
// https://github.com/facebook/react/pull/32465
|
|
14059
|
-
createFragmentInstance: (_fiber) => null,
|
|
14060
|
-
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
14061
|
-
},
|
|
14062
|
-
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
14063
|
-
},
|
|
14064
|
-
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
14065
|
-
},
|
|
14066
|
-
// https://github.com/facebook/react/pull/32653
|
|
14067
|
-
measureClonedInstance: (_instance) => null,
|
|
14068
|
-
// https://github.com/facebook/react/pull/32819
|
|
14069
|
-
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
14070
|
-
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
14071
|
-
// https://github.com/facebook/react/pull/34486
|
|
14072
|
-
startSuspendingCommit: () => null,
|
|
14073
|
-
// https://github.com/facebook/react/pull/34522
|
|
14074
|
-
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14075
|
-
});
|
|
14110
|
+
});
|
|
14111
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
14112
|
+
return rootStore;
|
|
14113
|
+
};
|
|
14114
|
+
|
|
14115
|
+
const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
|
|
14116
|
+
function getRegistry() {
|
|
14117
|
+
return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
|
|
14118
|
+
extensions: /* @__PURE__ */ new Map(),
|
|
14119
|
+
roots: /* @__PURE__ */ new Set(),
|
|
14120
|
+
applied: /* @__PURE__ */ new WeakMap()
|
|
14121
|
+
});
|
|
14122
|
+
}
|
|
14123
|
+
function setupRoot(registry, store, extension) {
|
|
14124
|
+
let applied = registry.applied.get(store);
|
|
14125
|
+
if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
|
|
14126
|
+
if (applied.has(extension.name)) return;
|
|
14127
|
+
applied.set(extension.name, extension);
|
|
14128
|
+
const patch = extension.setup?.(store);
|
|
14129
|
+
if (patch) store.setState(patch);
|
|
14130
|
+
}
|
|
14131
|
+
function registerRootExtension(extension) {
|
|
14132
|
+
const registry = getRegistry();
|
|
14133
|
+
registry.extensions.set(extension.name, extension);
|
|
14134
|
+
for (const store of registry.roots) setupRoot(registry, store, extension);
|
|
14135
|
+
return () => {
|
|
14136
|
+
if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
|
|
14137
|
+
};
|
|
14138
|
+
}
|
|
14139
|
+
function setRenderOverride(store, render) {
|
|
14140
|
+
store.getState().internal.renderOverride = render;
|
|
14141
|
+
}
|
|
14142
|
+
function attachRootExtensions(store) {
|
|
14143
|
+
const registry = getRegistry();
|
|
14144
|
+
registry.roots.add(store);
|
|
14145
|
+
for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
|
|
14146
|
+
}
|
|
14147
|
+
function current(registry, setUpBy) {
|
|
14148
|
+
return registry.extensions.get(setUpBy.name) ?? setUpBy;
|
|
14149
|
+
}
|
|
14150
|
+
function detachRootExtensions(store) {
|
|
14151
|
+
const registry = getRegistry();
|
|
14152
|
+
if (!registry.roots.delete(store)) return;
|
|
14153
|
+
const applied = registry.applied.get(store);
|
|
14154
|
+
registry.applied.delete(store);
|
|
14155
|
+
if (!applied) return;
|
|
14156
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
|
|
14157
|
+
}
|
|
14158
|
+
function notifyRootExtensionsHmr(store) {
|
|
14159
|
+
const registry = getRegistry();
|
|
14160
|
+
const applied = registry.applied.get(store);
|
|
14161
|
+
if (!applied) return;
|
|
14162
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
|
|
14163
|
+
}
|
|
14076
14164
|
|
|
14077
14165
|
const isRenderer = (def) => !!def?.render;
|
|
14078
14166
|
const _roots = /* @__PURE__ */ new Map();
|
|
@@ -14307,7 +14395,7 @@ function createRoot(canvas) {
|
|
|
14307
14395
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14308
14396
|
const state2 = store.getState();
|
|
14309
14397
|
if (state2.frameloop === "never") return;
|
|
14310
|
-
advance(timestamp);
|
|
14398
|
+
advance(timestamp, true, state2);
|
|
14311
14399
|
};
|
|
14312
14400
|
const actualRenderer = state.internal.actualRenderer;
|
|
14313
14401
|
const handleSessionChange = () => {
|
|
@@ -14315,7 +14403,7 @@ function createRoot(canvas) {
|
|
|
14315
14403
|
const renderer2 = state2.internal.actualRenderer;
|
|
14316
14404
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14317
14405
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14318
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14406
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14319
14407
|
};
|
|
14320
14408
|
const xr = {
|
|
14321
14409
|
connect() {
|
|
@@ -14397,14 +14485,23 @@ function createRoot(canvas) {
|
|
|
14397
14485
|
const newRootId = canvasId || scheduler$1.generateRootId();
|
|
14398
14486
|
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
14399
14487
|
getState: () => store.getState(),
|
|
14400
|
-
onError: (err) => store.getState().setError(err)
|
|
14488
|
+
onError: (err) => store.getState().setError(err),
|
|
14489
|
+
frameloop: store.getState().frameloop,
|
|
14490
|
+
before: schedulerConfig?.before,
|
|
14491
|
+
after: schedulerConfig?.after,
|
|
14492
|
+
order: schedulerConfig?.order
|
|
14401
14493
|
});
|
|
14402
14494
|
const unregisterCanvasTarget = scheduler$1.register(
|
|
14403
14495
|
() => {
|
|
14404
14496
|
const state2 = store.getState();
|
|
14405
|
-
|
|
14497
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14498
|
+
if (canvasTarget) {
|
|
14406
14499
|
const renderer2 = state2.internal.actualRenderer;
|
|
14407
|
-
renderer2.setCanvasTarget(
|
|
14500
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14501
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14502
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14503
|
+
renderer2.backend?.updateSize?.();
|
|
14504
|
+
}
|
|
14408
14505
|
}
|
|
14409
14506
|
},
|
|
14410
14507
|
{
|
|
@@ -14460,7 +14557,8 @@ function createRoot(canvas) {
|
|
|
14460
14557
|
const userHandlesRender = scheduler$1.hasUserJobsInPhase("render", newRootId);
|
|
14461
14558
|
if (userHandlesRender || state2.internal.priority) return;
|
|
14462
14559
|
try {
|
|
14463
|
-
|
|
14560
|
+
const renderOverride = state2.internal.renderOverride;
|
|
14561
|
+
if (renderOverride) renderOverride();
|
|
14464
14562
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
14465
14563
|
} catch (error) {
|
|
14466
14564
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -14473,8 +14571,7 @@ function createRoot(canvas) {
|
|
|
14473
14571
|
phase: "render",
|
|
14474
14572
|
system: true,
|
|
14475
14573
|
// Internal flag: this is a system job, not user-controlled
|
|
14476
|
-
//
|
|
14477
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14574
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14478
14575
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14479
14576
|
}
|
|
14480
14577
|
);
|
|
@@ -14493,8 +14590,22 @@ function createRoot(canvas) {
|
|
|
14493
14590
|
scheduler: scheduler$1
|
|
14494
14591
|
}
|
|
14495
14592
|
}));
|
|
14593
|
+
} else {
|
|
14594
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14595
|
+
if (constraintsChanged) {
|
|
14596
|
+
scheduler$1.setRootConstraints(rootId, {
|
|
14597
|
+
before: schedulerConfig?.before,
|
|
14598
|
+
after: schedulerConfig?.after
|
|
14599
|
+
});
|
|
14600
|
+
}
|
|
14601
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14602
|
+
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14603
|
+
}
|
|
14496
14604
|
}
|
|
14497
|
-
|
|
14605
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14606
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14607
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14608
|
+
attachRootExtensions(store);
|
|
14498
14609
|
onCreated = onCreatedCallback;
|
|
14499
14610
|
configured = true;
|
|
14500
14611
|
resolve();
|
|
@@ -14536,18 +14647,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14536
14647
|
const fiber = root?.fiber;
|
|
14537
14648
|
if (fiber) {
|
|
14538
14649
|
const state = root?.store.getState();
|
|
14539
|
-
if (state)
|
|
14650
|
+
if (state) {
|
|
14651
|
+
state.internal.active = false;
|
|
14652
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14653
|
+
if (unregisterRoot) {
|
|
14654
|
+
unregisterRoot();
|
|
14655
|
+
state.internal.unregisterRoot = void 0;
|
|
14656
|
+
}
|
|
14657
|
+
}
|
|
14540
14658
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14659
|
+
if (root?.store) detachRootExtensions(root.store);
|
|
14541
14660
|
if (state) {
|
|
14542
14661
|
setTimeout(() => {
|
|
14543
14662
|
try {
|
|
14544
14663
|
const renderer = state.internal.actualRenderer;
|
|
14545
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14546
|
-
if (unregisterRoot) unregisterRoot();
|
|
14547
14664
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14548
14665
|
if (unregisterPrimary) unregisterPrimary();
|
|
14549
14666
|
const canvasTarget = state.internal.canvasTarget;
|
|
14550
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14667
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14551
14668
|
state.events.disconnect?.();
|
|
14552
14669
|
cleanupHelperGroup(root.store);
|
|
14553
14670
|
if (state.isLegacy && renderer) {
|
|
@@ -14688,16 +14805,11 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14688
14805
|
const oldbg = target.background;
|
|
14689
14806
|
const oldenv = target.environment;
|
|
14690
14807
|
const oldSceneProps = {
|
|
14691
|
-
// @ts-ignore
|
|
14692
14808
|
backgroundBlurriness: target.backgroundBlurriness,
|
|
14693
|
-
// @ts-ignore
|
|
14694
14809
|
backgroundIntensity: target.backgroundIntensity,
|
|
14695
|
-
|
|
14696
|
-
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
14697
|
-
// @ts-ignore
|
|
14810
|
+
backgroundRotation: target.backgroundRotation.clone(),
|
|
14698
14811
|
environmentIntensity: target.environmentIntensity,
|
|
14699
|
-
|
|
14700
|
-
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
14812
|
+
environmentRotation: target.environmentRotation.clone()
|
|
14701
14813
|
};
|
|
14702
14814
|
if (background !== "only") target.environment = texture;
|
|
14703
14815
|
if (background) target.background = texture;
|
|
@@ -14709,7 +14821,7 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14709
14821
|
};
|
|
14710
14822
|
}
|
|
14711
14823
|
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
14712
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14824
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14713
14825
|
React__namespace.useLayoutEffect(() => {
|
|
14714
14826
|
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
14715
14827
|
});
|
|
@@ -14727,7 +14839,7 @@ function EnvironmentCube({
|
|
|
14727
14839
|
...rest
|
|
14728
14840
|
}) {
|
|
14729
14841
|
const texture = useEnvironment(rest);
|
|
14730
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14842
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14731
14843
|
React__namespace.useLayoutEffect(() => {
|
|
14732
14844
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
14733
14845
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -14764,9 +14876,9 @@ function EnvironmentPortal({
|
|
|
14764
14876
|
preset = void 0,
|
|
14765
14877
|
extensions
|
|
14766
14878
|
}) {
|
|
14767
|
-
const renderer = useThree((state) => state.renderer);
|
|
14768
|
-
const isLegacy = useThree((state) => state.isLegacy);
|
|
14769
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14879
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
14880
|
+
const isLegacy = useThree$1((state) => state.isLegacy);
|
|
14881
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14770
14882
|
const camera = React__namespace.useRef(null);
|
|
14771
14883
|
const [virtualScene] = React__namespace.useState(() => new three.Scene());
|
|
14772
14884
|
const fbo = React__namespace.useMemo(() => {
|
|
@@ -14810,7 +14922,7 @@ function EnvironmentPortal({
|
|
|
14810
14922
|
environmentRotation
|
|
14811
14923
|
]);
|
|
14812
14924
|
let count = 1;
|
|
14813
|
-
useFrame(() => {
|
|
14925
|
+
useFrame$1(() => {
|
|
14814
14926
|
if (frames === Infinity || count < frames) {
|
|
14815
14927
|
const autoClear = renderer.autoClear;
|
|
14816
14928
|
renderer.autoClear = true;
|
|
@@ -14850,7 +14962,7 @@ function EnvironmentGround(props) {
|
|
|
14850
14962
|
] });
|
|
14851
14963
|
}
|
|
14852
14964
|
function EnvironmentColor({ color, scene }) {
|
|
14853
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14965
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14854
14966
|
React__namespace.useLayoutEffect(() => {
|
|
14855
14967
|
if (color === void 0) return;
|
|
14856
14968
|
const target = resolveScene(scene || defaultScene);
|
|
@@ -14922,38 +15034,6 @@ function parseRendererConfig(rendererProp) {
|
|
|
14922
15034
|
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
14923
15035
|
}
|
|
14924
15036
|
|
|
14925
|
-
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
14926
|
-
const registries = /* @__PURE__ */ new WeakMap();
|
|
14927
|
-
function getKindRegistry(store, kind) {
|
|
14928
|
-
let registry = registries.get(store);
|
|
14929
|
-
if (!registry) {
|
|
14930
|
-
registry = {
|
|
14931
|
-
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14932
|
-
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14933
|
-
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14934
|
-
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
14935
|
-
};
|
|
14936
|
-
registries.set(store, registry);
|
|
14937
|
-
}
|
|
14938
|
-
return registry[kind];
|
|
14939
|
-
}
|
|
14940
|
-
function invalidateResource(store, kind, scopeKey) {
|
|
14941
|
-
const registry = getKindRegistry(store, kind);
|
|
14942
|
-
{
|
|
14943
|
-
registry.valid.clear();
|
|
14944
|
-
registry.staged.clear();
|
|
14945
|
-
}
|
|
14946
|
-
}
|
|
14947
|
-
function invalidateAllResources(store) {
|
|
14948
|
-
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
14949
|
-
}
|
|
14950
|
-
|
|
14951
|
-
function clearHmrCaches(store) {
|
|
14952
|
-
const primary = store.getState().primaryStore ?? store;
|
|
14953
|
-
invalidateAllResources(primary);
|
|
14954
|
-
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
14955
|
-
}
|
|
14956
|
-
|
|
14957
15037
|
function CanvasImpl({
|
|
14958
15038
|
ref,
|
|
14959
15039
|
children,
|
|
@@ -14991,9 +15071,9 @@ function CanvasImpl({
|
|
|
14991
15071
|
React__namespace.useMemo(() => extend(THREE), []);
|
|
14992
15072
|
const Bridge = useBridge();
|
|
14993
15073
|
const backgroundProps = React__namespace.useMemo(() => parseBackground(background), [background]);
|
|
14994
|
-
const
|
|
15074
|
+
const [hasInitialSize, setHasInitialSize] = React__namespace.useState(false);
|
|
14995
15075
|
const measureConfig = React__namespace.useMemo(() => {
|
|
14996
|
-
if (!
|
|
15076
|
+
if (!hasInitialSize) {
|
|
14997
15077
|
return {
|
|
14998
15078
|
...resize,
|
|
14999
15079
|
scroll: resize?.scroll ?? true,
|
|
@@ -15005,7 +15085,7 @@ function CanvasImpl({
|
|
|
15005
15085
|
debounce: { scroll: 50, resize: 0 },
|
|
15006
15086
|
...resize
|
|
15007
15087
|
};
|
|
15008
|
-
}, [
|
|
15088
|
+
}, [hasInitialSize, resize]);
|
|
15009
15089
|
const [containerRef, containerRect] = useMeasure__default(measureConfig);
|
|
15010
15090
|
const effectiveSize = React__namespace.useMemo(() => {
|
|
15011
15091
|
let w = width ?? containerRect.width;
|
|
@@ -15021,9 +15101,7 @@ function CanvasImpl({
|
|
|
15021
15101
|
left: containerRect.left
|
|
15022
15102
|
};
|
|
15023
15103
|
}, [width, height, containerRect, forceEven]);
|
|
15024
|
-
if (!
|
|
15025
|
-
hasInitialSizeRef.current = true;
|
|
15026
|
-
}
|
|
15104
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15027
15105
|
const canvasRef = React__namespace.useRef(null);
|
|
15028
15106
|
const divRef = React__namespace.useRef(null);
|
|
15029
15107
|
React__namespace.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15137,6 +15215,7 @@ function CanvasImpl({
|
|
|
15137
15215
|
const canvas = canvasRef.current;
|
|
15138
15216
|
if (canvas) {
|
|
15139
15217
|
return () => {
|
|
15218
|
+
if (canvas.isConnected) return;
|
|
15140
15219
|
unmountComponentAtNode(canvas);
|
|
15141
15220
|
root.current = null;
|
|
15142
15221
|
};
|
|
@@ -15149,7 +15228,7 @@ function CanvasImpl({
|
|
|
15149
15228
|
const handleHMR = () => {
|
|
15150
15229
|
queueMicrotask(() => {
|
|
15151
15230
|
const rootEntry = _roots.get(canvas);
|
|
15152
|
-
if (rootEntry?.store)
|
|
15231
|
+
if (rootEntry?.store) notifyRootExtensionsHmr(rootEntry.store);
|
|
15153
15232
|
});
|
|
15154
15233
|
};
|
|
15155
15234
|
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('legacy.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
@@ -15195,11 +15274,14 @@ function CanvasImpl({
|
|
|
15195
15274
|
}
|
|
15196
15275
|
);
|
|
15197
15276
|
}
|
|
15198
|
-
function Canvas(props) {
|
|
15277
|
+
function Canvas$1(props) {
|
|
15199
15278
|
return /* @__PURE__ */ jsxRuntime.jsx(itsFine.FiberProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(CanvasImpl, { ...props }) });
|
|
15200
15279
|
}
|
|
15201
15280
|
|
|
15202
15281
|
extend(THREE);
|
|
15282
|
+
const useThree = useThree$1;
|
|
15283
|
+
const useFrame = useFrame$1;
|
|
15284
|
+
const Canvas = Canvas$1;
|
|
15203
15285
|
|
|
15204
15286
|
exports.Scheduler = scheduler.Scheduler;
|
|
15205
15287
|
exports.getScheduler = scheduler.getScheduler;
|
|
@@ -15267,8 +15349,10 @@ exports.prepare = prepare;
|
|
|
15267
15349
|
exports.presetsObj = presetsObj;
|
|
15268
15350
|
exports.reconciler = reconciler;
|
|
15269
15351
|
exports.registerPrimary = registerPrimary;
|
|
15352
|
+
exports.registerRootExtension = registerRootExtension;
|
|
15270
15353
|
exports.removeInteractivity = removeInteractivity;
|
|
15271
15354
|
exports.resolve = resolve;
|
|
15355
|
+
exports.setRenderOverride = setRenderOverride;
|
|
15272
15356
|
exports.swapInteractivity = swapInteractivity;
|
|
15273
15357
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
15274
15358
|
exports.unregisterPrimary = unregisterPrimary;
|