@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/index.cjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const webgpu = require('three/webgpu');
|
|
4
4
|
const three = require('three');
|
|
5
|
-
const Inspector_js = require('three/addons/inspector/Inspector.js');
|
|
6
5
|
const jsxRuntime = require('react/jsx-runtime');
|
|
7
6
|
const React = require('react');
|
|
8
7
|
const useMeasure = require('react-use-measure');
|
|
@@ -12,6 +11,7 @@ const scheduler = require('@pmndrs/scheduler');
|
|
|
12
11
|
const Tb = require('scheduler');
|
|
13
12
|
const GroundedSkybox_js = require('three/examples/jsm/objects/GroundedSkybox.js');
|
|
14
13
|
const HDRLoader_js = require('three/examples/jsm/loaders/HDRLoader.js');
|
|
14
|
+
const HDRCubeTextureLoader_js = require('three/examples/jsm/loaders/HDRCubeTextureLoader.js');
|
|
15
15
|
const EXRLoader_js = require('three/examples/jsm/loaders/EXRLoader.js');
|
|
16
16
|
const UltraHDRLoader_js = require('three/examples/jsm/loaders/UltraHDRLoader.js');
|
|
17
17
|
const gainmapJs = require('@monogrid/gainmap-js');
|
|
@@ -52,18 +52,22 @@ const Tb__default = /*#__PURE__*/_interopDefaultCompat(Tb);
|
|
|
52
52
|
|
|
53
53
|
const R3F_BUILD_LEGACY = true;
|
|
54
54
|
const R3F_BUILD_WEBGPU = true;
|
|
55
|
+
async function loadInspector() {
|
|
56
|
+
const { Inspector } = await import('three/addons/inspector/Inspector.js');
|
|
57
|
+
return Inspector;
|
|
58
|
+
}
|
|
55
59
|
|
|
56
60
|
const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
57
61
|
__proto__: null,
|
|
58
62
|
CubeRenderTarget: webgpu.CubeRenderTarget,
|
|
59
63
|
CubeRenderTargetCompat: webgpu.CubeRenderTarget,
|
|
60
|
-
Inspector: Inspector_js.Inspector,
|
|
61
64
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
62
65
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
63
66
|
RenderTargetCompat: webgpu.RenderTarget,
|
|
64
67
|
WebGLCubeRenderTarget: three.WebGLCubeRenderTarget,
|
|
65
68
|
WebGLRenderTarget: three.WebGLRenderTarget,
|
|
66
|
-
WebGLRenderer: three.WebGLRenderer
|
|
69
|
+
WebGLRenderer: three.WebGLRenderer,
|
|
70
|
+
loadInspector: loadInspector
|
|
67
71
|
}, [webgpu__namespace]);
|
|
68
72
|
|
|
69
73
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -310,7 +314,6 @@ function prepare(target, root, type, props) {
|
|
|
310
314
|
}
|
|
311
315
|
function invalidateInstance(instance) {
|
|
312
316
|
if (!instance.parent) return;
|
|
313
|
-
instance.props.onUpdate?.(instance.object);
|
|
314
317
|
const state = instance.root?.getState?.();
|
|
315
318
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
316
319
|
}
|
|
@@ -526,8 +529,10 @@ function hasVisibilityHandlers(handlers) {
|
|
|
526
529
|
}
|
|
527
530
|
|
|
528
531
|
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
529
|
-
function fromRef(ref) {
|
|
530
|
-
|
|
532
|
+
function fromRef(ref, transform) {
|
|
533
|
+
const marker = { [FROM_REF]: ref };
|
|
534
|
+
if (transform) marker.transform = transform;
|
|
535
|
+
return marker;
|
|
531
536
|
}
|
|
532
537
|
function isFromRef(value) {
|
|
533
538
|
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
@@ -541,6 +546,63 @@ function isOnce(value) {
|
|
|
541
546
|
return value !== null && typeof value === "object" && ONCE in value;
|
|
542
547
|
}
|
|
543
548
|
|
|
549
|
+
const shownNotices = /* @__PURE__ */ new Set();
|
|
550
|
+
function notifyDepreciated({ heading, body, link }) {
|
|
551
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
if (shownNotices.has(heading)) return;
|
|
555
|
+
shownNotices.add(heading);
|
|
556
|
+
const caller = getCallerFrame();
|
|
557
|
+
if (caller) {
|
|
558
|
+
console.log();
|
|
559
|
+
}
|
|
560
|
+
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
561
|
+
if (caller) {
|
|
562
|
+
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
563
|
+
}
|
|
564
|
+
if (body || link) {
|
|
565
|
+
let message = "";
|
|
566
|
+
if (body) message += body;
|
|
567
|
+
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
568
|
+
console.warn(`%c${message}`, "font-weight: bold;");
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
function getCallerFrame(depth = 3) {
|
|
572
|
+
const stack = new Error().stack;
|
|
573
|
+
if (!stack) return null;
|
|
574
|
+
const lines = stack.split("\n");
|
|
575
|
+
const frame = lines[depth];
|
|
576
|
+
if (!frame) return null;
|
|
577
|
+
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
578
|
+
if (!match) {
|
|
579
|
+
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
580
|
+
}
|
|
581
|
+
if (!match) return null;
|
|
582
|
+
const [, fn, url, line] = match;
|
|
583
|
+
return {
|
|
584
|
+
functionName: fn ?? "<anonymous>",
|
|
585
|
+
location: formatLocation(url, Number(line))
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
function formatLocation(url, line) {
|
|
589
|
+
const clean = url.split("?")[0];
|
|
590
|
+
const file = clean.split("/").pop() ?? clean;
|
|
591
|
+
return `${file}:${line}`;
|
|
592
|
+
}
|
|
593
|
+
function notifyAlpha({ message, link }) {
|
|
594
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
if (shownNotices.has(message)) return;
|
|
598
|
+
shownNotices.add(message);
|
|
599
|
+
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
600
|
+
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
601
|
+
{
|
|
602
|
+
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
544
606
|
const RESERVED_PROPS = [
|
|
545
607
|
"children",
|
|
546
608
|
"key",
|
|
@@ -550,7 +612,6 @@ const RESERVED_PROPS = [
|
|
|
550
612
|
"dispose",
|
|
551
613
|
"attach",
|
|
552
614
|
"object",
|
|
553
|
-
"onUpdate",
|
|
554
615
|
// Behavior flags
|
|
555
616
|
"dispose"
|
|
556
617
|
];
|
|
@@ -628,11 +689,9 @@ function diffProps(instance, newProps) {
|
|
|
628
689
|
for (const prop in instance.props) {
|
|
629
690
|
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
630
691
|
const { root, key } = resolve(instance.object, prop);
|
|
631
|
-
if (
|
|
692
|
+
if (typeof root?.constructor === "function") {
|
|
632
693
|
const ctor = getMemoizedPrototype(root);
|
|
633
694
|
if (!is.und(ctor)) changedProps[prop] = ctor[key];
|
|
634
|
-
} else {
|
|
635
|
-
changedProps[prop] = 0;
|
|
636
695
|
}
|
|
637
696
|
}
|
|
638
697
|
return changedProps;
|
|
@@ -644,6 +703,13 @@ function applyProps(object, props) {
|
|
|
644
703
|
for (const prop in props) {
|
|
645
704
|
const value = props[prop];
|
|
646
705
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
706
|
+
if (prop === "onUpdate") {
|
|
707
|
+
notifyDepreciated({
|
|
708
|
+
heading: "onUpdate is no longer an R3F prop",
|
|
709
|
+
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.",
|
|
710
|
+
link: "https://docs.pmnd.rs/react-three-fiber/migration/v10#onupdate-removed"
|
|
711
|
+
});
|
|
712
|
+
}
|
|
647
713
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
648
714
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
649
715
|
else delete instance.handlers[prop];
|
|
@@ -749,682 +815,378 @@ function applyProps(object, props) {
|
|
|
749
815
|
return object;
|
|
750
816
|
}
|
|
751
817
|
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
const caller = getCallerFrame();
|
|
760
|
-
if (caller) {
|
|
761
|
-
console.log();
|
|
762
|
-
}
|
|
763
|
-
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
764
|
-
if (caller) {
|
|
765
|
-
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
766
|
-
}
|
|
767
|
-
if (body || link) {
|
|
768
|
-
let message = "";
|
|
769
|
-
if (body) message += body;
|
|
770
|
-
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
771
|
-
console.warn(`%c${message}`, "font-weight: bold;");
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function getCallerFrame(depth = 3) {
|
|
775
|
-
const stack = new Error().stack;
|
|
776
|
-
if (!stack) return null;
|
|
777
|
-
const lines = stack.split("\n");
|
|
778
|
-
const frame = lines[depth];
|
|
779
|
-
if (!frame) return null;
|
|
780
|
-
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
781
|
-
if (!match) {
|
|
782
|
-
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
783
|
-
}
|
|
784
|
-
if (!match) return null;
|
|
785
|
-
const [, fn, url, line] = match;
|
|
786
|
-
return {
|
|
787
|
-
functionName: fn ?? "<anonymous>",
|
|
788
|
-
location: formatLocation(url, Number(line))
|
|
789
|
-
};
|
|
818
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
819
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React__namespace.createContext(null));
|
|
820
|
+
|
|
821
|
+
function useStore() {
|
|
822
|
+
const store = React.useContext(context);
|
|
823
|
+
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
824
|
+
return store;
|
|
790
825
|
}
|
|
791
|
-
function
|
|
792
|
-
|
|
793
|
-
const file = clean.split("/").pop() ?? clean;
|
|
794
|
-
return `${file}:${line}`;
|
|
826
|
+
function useThree(selector = (state) => state, equalityFn) {
|
|
827
|
+
return useStore()(selector, equalityFn);
|
|
795
828
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
if (
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
829
|
+
|
|
830
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
831
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
832
|
+
function getLoader$1(Proto) {
|
|
833
|
+
if (isConstructor$1(Proto)) {
|
|
834
|
+
let loader = memoizedLoaders.get(Proto);
|
|
835
|
+
if (!loader) {
|
|
836
|
+
loader = new Proto();
|
|
837
|
+
memoizedLoaders.set(Proto, loader);
|
|
838
|
+
}
|
|
839
|
+
return loader;
|
|
806
840
|
}
|
|
841
|
+
return Proto;
|
|
807
842
|
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
843
|
+
function loadingFn(extensions, onProgress) {
|
|
844
|
+
return function(Proto, input) {
|
|
845
|
+
const loader = getLoader$1(Proto);
|
|
846
|
+
if (extensions) extensions(loader);
|
|
847
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
848
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
849
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
850
|
+
return data;
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
return new Promise(
|
|
854
|
+
(res, reject) => loader.load(
|
|
855
|
+
input,
|
|
856
|
+
(data) => {
|
|
857
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
858
|
+
res(data);
|
|
859
|
+
},
|
|
860
|
+
onProgress,
|
|
861
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
862
|
+
)
|
|
863
|
+
);
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
867
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
868
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
869
|
+
const fn = loadingFn(extensions, onProgress);
|
|
870
|
+
const results = cacheKeys.map(
|
|
871
|
+
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
872
|
+
);
|
|
873
|
+
const stableRef = React.useRef(null);
|
|
874
|
+
const previous = stableRef.current;
|
|
875
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
876
|
+
stableRef.current = stable;
|
|
877
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
814
878
|
}
|
|
879
|
+
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
880
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
881
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
882
|
+
cacheKeys.forEach(
|
|
883
|
+
(key, index) => suspendReact.preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
884
|
+
);
|
|
885
|
+
};
|
|
886
|
+
useLoader.clear = function(loader, input, cacheKey) {
|
|
887
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
888
|
+
cacheKeys.forEach((key) => suspendReact.clear([loader, key]));
|
|
889
|
+
};
|
|
890
|
+
useLoader.loader = getLoader$1;
|
|
815
891
|
|
|
816
|
-
|
|
817
|
-
const
|
|
818
|
-
const
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
892
|
+
function useFrame(callback, priorityOrOptions) {
|
|
893
|
+
const store = React__namespace.useContext(context);
|
|
894
|
+
const isInsideCanvas = store !== null;
|
|
895
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
896
|
+
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
897
|
+
id: priorityOrOptions.id,
|
|
898
|
+
phase: priorityOrOptions.phase,
|
|
899
|
+
priority: priorityOrOptions.priority,
|
|
900
|
+
fps: priorityOrOptions.fps,
|
|
901
|
+
drop: priorityOrOptions.drop,
|
|
902
|
+
enabled: priorityOrOptions.enabled,
|
|
903
|
+
before: priorityOrOptions.before,
|
|
904
|
+
after: priorityOrOptions.after
|
|
905
|
+
}) : "";
|
|
906
|
+
const options = React__namespace.useMemo(() => {
|
|
907
|
+
return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
|
|
908
|
+
}, [optionsKey]);
|
|
909
|
+
const reactId = React__namespace.useId();
|
|
910
|
+
const id = options.id ?? reactId;
|
|
911
|
+
const callbackRef = useMutableCallback(callback);
|
|
912
|
+
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
913
|
+
useIsomorphicLayoutEffect(() => {
|
|
914
|
+
if (!callback) return;
|
|
915
|
+
if (isInsideCanvas) {
|
|
916
|
+
const state = store.getState();
|
|
917
|
+
const rootId = state.internal.rootId;
|
|
918
|
+
if (isLegacyPriority) {
|
|
919
|
+
state.internal.priority++;
|
|
920
|
+
let parentRoot = state.previousRoot;
|
|
921
|
+
while (parentRoot) {
|
|
922
|
+
const parentState = parentRoot.getState();
|
|
923
|
+
if (parentState?.internal) parentState.internal.priority++;
|
|
924
|
+
parentRoot = parentState?.previousRoot;
|
|
925
|
+
}
|
|
926
|
+
notifyDepreciated({
|
|
927
|
+
heading: "useFrame with numeric priority is deprecated",
|
|
928
|
+
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 })',
|
|
929
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
930
|
+
});
|
|
836
931
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
inspector: null,
|
|
865
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
866
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
867
|
-
textureColorSpace: webgpu.SRGBColorSpace,
|
|
868
|
-
isLegacy: false,
|
|
869
|
-
webGPUSupported: false,
|
|
870
|
-
isNative: false,
|
|
871
|
-
controls: null,
|
|
872
|
-
pointer,
|
|
873
|
-
mouse: pointer,
|
|
874
|
-
frameloop: "always",
|
|
875
|
-
onPointerMissed: void 0,
|
|
876
|
-
onDragOverMissed: void 0,
|
|
877
|
-
onDropMissed: void 0,
|
|
878
|
-
performance: {
|
|
879
|
-
current: 1,
|
|
880
|
-
min: 0.5,
|
|
881
|
-
max: 1,
|
|
882
|
-
debounce: 200,
|
|
883
|
-
regress: () => {
|
|
884
|
-
const state2 = get();
|
|
885
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
886
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
887
|
-
performanceTimeout = setTimeout(
|
|
888
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
889
|
-
state2.performance.debounce
|
|
890
|
-
);
|
|
891
|
-
}
|
|
892
|
-
},
|
|
893
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
894
|
-
viewport: {
|
|
895
|
-
initialDpr: 0,
|
|
896
|
-
dpr: 0,
|
|
897
|
-
width: 0,
|
|
898
|
-
height: 0,
|
|
899
|
-
top: 0,
|
|
900
|
-
left: 0,
|
|
901
|
-
aspect: 0,
|
|
902
|
-
distance: 0,
|
|
903
|
-
factor: 0,
|
|
904
|
-
getCurrentViewport
|
|
905
|
-
},
|
|
906
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
907
|
-
setSize: (width, height, top, left) => {
|
|
908
|
-
const state2 = get();
|
|
909
|
-
if (width === void 0) {
|
|
910
|
-
set({ _sizeImperative: false });
|
|
911
|
-
if (state2._sizeProps) {
|
|
912
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
913
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
914
|
-
const currentSize = state2.size;
|
|
915
|
-
const newSize = {
|
|
916
|
-
width: propW ?? currentSize.width,
|
|
917
|
-
height: propH ?? currentSize.height,
|
|
918
|
-
top: currentSize.top,
|
|
919
|
-
left: currentSize.left
|
|
920
|
-
};
|
|
921
|
-
set((s) => ({
|
|
922
|
-
size: newSize,
|
|
923
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
924
|
-
}));
|
|
925
|
-
scheduler.getScheduler().invalidate();
|
|
932
|
+
const wrappedCallback = (frameState, delta) => {
|
|
933
|
+
const localState = store.getState();
|
|
934
|
+
const mergedState = {
|
|
935
|
+
...localState,
|
|
936
|
+
time: frameState.time,
|
|
937
|
+
delta: frameState.delta,
|
|
938
|
+
elapsed: frameState.elapsed,
|
|
939
|
+
frame: frameState.frame
|
|
940
|
+
};
|
|
941
|
+
callbackRef.current?.(mergedState, delta);
|
|
942
|
+
};
|
|
943
|
+
const unregister = scheduler$1.register(wrappedCallback, {
|
|
944
|
+
id,
|
|
945
|
+
rootId,
|
|
946
|
+
...options
|
|
947
|
+
});
|
|
948
|
+
return () => {
|
|
949
|
+
unregister();
|
|
950
|
+
if (isLegacyPriority) {
|
|
951
|
+
const currentState = store.getState();
|
|
952
|
+
if (currentState.internal) {
|
|
953
|
+
currentState.internal.priority--;
|
|
954
|
+
let parentRoot = currentState.previousRoot;
|
|
955
|
+
while (parentRoot) {
|
|
956
|
+
const parentState = parentRoot.getState();
|
|
957
|
+
if (parentState?.internal) parentState.internal.priority--;
|
|
958
|
+
parentRoot = parentState?.previousRoot;
|
|
926
959
|
}
|
|
927
960
|
}
|
|
928
|
-
return;
|
|
929
961
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
962
|
+
};
|
|
963
|
+
} else {
|
|
964
|
+
return scheduler$1.register(
|
|
965
|
+
(state, delta) => {
|
|
966
|
+
const frameState = state;
|
|
967
|
+
if (!frameState.renderer) return;
|
|
968
|
+
callbackRef.current?.(frameState, delta);
|
|
969
|
+
},
|
|
970
|
+
{ id, ...options }
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
}, [store, scheduler$1, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
974
|
+
const isPaused = React__namespace.useSyncExternalStore(
|
|
975
|
+
// Subscribe function
|
|
976
|
+
React__namespace.useCallback(
|
|
977
|
+
(onStoreChange) => {
|
|
978
|
+
return scheduler.getScheduler().subscribeJobState(id, onStoreChange);
|
|
941
979
|
},
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
980
|
+
[id]
|
|
981
|
+
),
|
|
982
|
+
// getSnapshot function
|
|
983
|
+
React__namespace.useCallback(() => scheduler.getScheduler().isJobPaused(id), [id]),
|
|
984
|
+
// getServerSnapshot function (SSR)
|
|
985
|
+
React__namespace.useCallback(() => false, [])
|
|
986
|
+
);
|
|
987
|
+
const controls = React__namespace.useMemo(() => {
|
|
988
|
+
const scheduler2 = scheduler.getScheduler();
|
|
989
|
+
return {
|
|
990
|
+
/** The job's unique ID */
|
|
991
|
+
id,
|
|
992
|
+
/**
|
|
993
|
+
* Access to the global scheduler for frame loop control.
|
|
994
|
+
* Use for controlling the entire frame loop, adding phases, etc.
|
|
995
|
+
*/
|
|
996
|
+
scheduler: scheduler2,
|
|
997
|
+
/**
|
|
998
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
999
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1000
|
+
*/
|
|
1001
|
+
get rootId() {
|
|
1002
|
+
return scheduler.getScheduler().getJobRootId(id);
|
|
949
1003
|
},
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
internal.subscribers.push({ ref, priority, store });
|
|
993
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
994
|
-
return () => {
|
|
995
|
-
const internal2 = get().internal;
|
|
996
|
-
if (internal2?.subscribers) {
|
|
997
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
998
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
999
|
-
}
|
|
1000
|
-
};
|
|
1001
|
-
},
|
|
1002
|
-
// Renderer Storage (single source of truth)
|
|
1003
|
-
actualRenderer: null,
|
|
1004
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
1005
|
-
scheduler: null
|
|
1006
|
-
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Manually step this job only.
|
|
1006
|
+
* Bypasses FPS limiting - always runs.
|
|
1007
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1008
|
+
*/
|
|
1009
|
+
step: (timestamp) => {
|
|
1010
|
+
scheduler.getScheduler().stepJob(id, timestamp);
|
|
1011
|
+
},
|
|
1012
|
+
/**
|
|
1013
|
+
* Manually step ALL jobs in the scheduler.
|
|
1014
|
+
* Useful for frameloop='never' mode.
|
|
1015
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1016
|
+
*/
|
|
1017
|
+
stepAll: (timestamp) => {
|
|
1018
|
+
scheduler.getScheduler().step(timestamp);
|
|
1019
|
+
},
|
|
1020
|
+
/**
|
|
1021
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1022
|
+
*/
|
|
1023
|
+
invalidate: (frames, stackFrames) => {
|
|
1024
|
+
const scheduler3 = scheduler.getScheduler();
|
|
1025
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1026
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1027
|
+
},
|
|
1028
|
+
/**
|
|
1029
|
+
* Pause this job (set enabled=false).
|
|
1030
|
+
* Job remains registered but won't run.
|
|
1031
|
+
*/
|
|
1032
|
+
pause: () => {
|
|
1033
|
+
scheduler.getScheduler().pauseJob(id);
|
|
1034
|
+
},
|
|
1035
|
+
/**
|
|
1036
|
+
* Resume this job (set enabled=true).
|
|
1037
|
+
*/
|
|
1038
|
+
resume: () => {
|
|
1039
|
+
scheduler.getScheduler().resumeJob(id);
|
|
1040
|
+
},
|
|
1041
|
+
/**
|
|
1042
|
+
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1043
|
+
* No need for forceUpdate() in your components.
|
|
1044
|
+
*/
|
|
1045
|
+
isPaused
|
|
1007
1046
|
};
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
Object.defineProperty(state, "gl", {
|
|
1012
|
-
get() {
|
|
1013
|
-
const currentState = rootStore.getState();
|
|
1014
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1015
|
-
const stack = new Error().stack || "";
|
|
1016
|
-
if (!isInternalRendererAccess(stack)) {
|
|
1017
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1018
|
-
notifyDepreciated({
|
|
1019
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1020
|
-
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
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
return currentState.internal.actualRenderer;
|
|
1025
|
-
},
|
|
1026
|
-
set(value) {
|
|
1027
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1028
|
-
},
|
|
1029
|
-
enumerable: true,
|
|
1030
|
-
configurable: true
|
|
1031
|
-
});
|
|
1032
|
-
Object.defineProperty(state, "renderer", {
|
|
1033
|
-
get() {
|
|
1034
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1035
|
-
},
|
|
1036
|
-
set(value) {
|
|
1037
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1038
|
-
},
|
|
1039
|
-
enumerable: true,
|
|
1040
|
-
configurable: true
|
|
1041
|
-
});
|
|
1042
|
-
let oldScene = state.scene;
|
|
1043
|
-
rootStore.subscribe(() => {
|
|
1044
|
-
const currentState = rootStore.getState();
|
|
1045
|
-
const { scene, rootScene, set } = currentState;
|
|
1046
|
-
if (scene !== oldScene) {
|
|
1047
|
-
oldScene = scene;
|
|
1048
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1049
|
-
set({ rootScene: scene });
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
});
|
|
1053
|
-
let oldSize = state.size;
|
|
1054
|
-
let oldDpr = state.viewport.dpr;
|
|
1055
|
-
let oldCamera = state.camera;
|
|
1056
|
-
rootStore.subscribe(() => {
|
|
1057
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1058
|
-
const actualRenderer = internal.actualRenderer;
|
|
1059
|
-
const canvasTarget = internal.canvasTarget;
|
|
1060
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1061
|
-
oldSize = size;
|
|
1062
|
-
oldDpr = viewport.dpr;
|
|
1063
|
-
updateCamera(camera, size);
|
|
1064
|
-
if (internal.isSecondary && canvasTarget) {
|
|
1065
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1066
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1067
|
-
} else {
|
|
1068
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1069
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1070
|
-
if (canvasTarget) {
|
|
1071
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1072
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
if (camera !== oldCamera) {
|
|
1077
|
-
oldCamera = camera;
|
|
1078
|
-
const { rootScene } = rootStore.getState();
|
|
1079
|
-
if (camera && rootScene && !camera.parent) {
|
|
1080
|
-
rootScene.add(camera);
|
|
1081
|
-
}
|
|
1082
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1083
|
-
const currentState = rootStore.getState();
|
|
1084
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1085
|
-
updateFrustum(camera, currentState.frustum);
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
});
|
|
1089
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
1090
|
-
return rootStore;
|
|
1091
|
-
};
|
|
1047
|
+
}, [id, isPaused]);
|
|
1048
|
+
return controls;
|
|
1049
|
+
}
|
|
1092
1050
|
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
if (
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1051
|
+
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1052
|
+
function getUrls(input) {
|
|
1053
|
+
if (typeof input === "string") return [input];
|
|
1054
|
+
if (Array.isArray(input)) return input;
|
|
1055
|
+
return Object.values(input);
|
|
1056
|
+
}
|
|
1057
|
+
function inputSignature(input) {
|
|
1058
|
+
if (typeof input === "string") return input;
|
|
1059
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1060
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1061
|
+
}
|
|
1062
|
+
function allUrlsCached(urls, textureCache) {
|
|
1063
|
+
return urls.every((url) => textureCache.has(url));
|
|
1064
|
+
}
|
|
1065
|
+
function buildFromCache(input, textureCache) {
|
|
1066
|
+
if (typeof input === "string") {
|
|
1067
|
+
return textureCache.get(input);
|
|
1068
|
+
} else if (Array.isArray(input)) {
|
|
1069
|
+
return input.map((url) => textureCache.get(url));
|
|
1070
|
+
} else {
|
|
1071
|
+
const result = {};
|
|
1072
|
+
const objInput = input;
|
|
1073
|
+
for (const key in objInput) {
|
|
1074
|
+
result[key] = textureCache.get(objInput[key]);
|
|
1101
1075
|
}
|
|
1102
|
-
return
|
|
1076
|
+
return result;
|
|
1103
1077
|
}
|
|
1104
|
-
return Proto;
|
|
1105
1078
|
}
|
|
1106
|
-
function
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1079
|
+
function useTexture(input, optionsOrOnLoad) {
|
|
1080
|
+
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1081
|
+
const store = useStore();
|
|
1082
|
+
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1083
|
+
const { onLoad, cache = true } = options;
|
|
1084
|
+
const onLoadRef = React.useRef(onLoad);
|
|
1085
|
+
onLoadRef.current = onLoad;
|
|
1086
|
+
const onLoadCalledForRef = React.useRef(null);
|
|
1087
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
1088
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
1089
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1090
|
+
const cachedResult = React.useMemo(() => {
|
|
1091
|
+
if (!cache) return null;
|
|
1092
|
+
const textures = store.getState().textures;
|
|
1093
|
+
if (!allUrlsCached(urls, textures)) return null;
|
|
1094
|
+
return buildFromCache(stableInput, textures);
|
|
1095
|
+
}, [cache, urls, stableInput, store]);
|
|
1096
|
+
const loadedTextures = useLoader(
|
|
1097
|
+
webgpu.TextureLoader,
|
|
1098
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1099
|
+
);
|
|
1100
|
+
const mappedTextures = React.useMemo(() => {
|
|
1101
|
+
if (cachedResult) return cachedResult;
|
|
1102
|
+
if (IsObject(stableInput)) {
|
|
1103
|
+
const keyed = {};
|
|
1104
|
+
const textureArray = loadedTextures;
|
|
1105
|
+
let i = 0;
|
|
1106
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1107
|
+
return keyed;
|
|
1108
|
+
} else {
|
|
1109
|
+
return loadedTextures;
|
|
1110
|
+
}
|
|
1111
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1112
|
+
React.useLayoutEffect(() => {
|
|
1113
|
+
if (cachedResult) return;
|
|
1114
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
1115
|
+
onLoadCalledForRef.current = inputKey;
|
|
1116
|
+
onLoadRef.current?.(mappedTextures);
|
|
1117
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
1118
|
+
React.useEffect(() => {
|
|
1119
|
+
if (cachedResult) return;
|
|
1120
|
+
if ("initTexture" in renderer) {
|
|
1121
|
+
let textureArray = [];
|
|
1122
|
+
if (Array.isArray(loadedTextures)) {
|
|
1123
|
+
textureArray = loadedTextures;
|
|
1124
|
+
} else if (loadedTextures instanceof webgpu.Texture) {
|
|
1125
|
+
textureArray = [loadedTextures];
|
|
1126
|
+
} else if (IsObject(loadedTextures)) {
|
|
1127
|
+
textureArray = Object.values(loadedTextures);
|
|
1128
|
+
}
|
|
1129
|
+
textureArray.forEach((texture) => {
|
|
1130
|
+
if (texture instanceof webgpu.Texture) {
|
|
1131
|
+
renderer.initTexture(texture);
|
|
1132
|
+
}
|
|
1114
1133
|
});
|
|
1115
1134
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1135
|
+
}, [renderer, loadedTextures, cachedResult]);
|
|
1136
|
+
React.useEffect(() => {
|
|
1137
|
+
if (!cache) return;
|
|
1138
|
+
const urlTextureMap = [];
|
|
1139
|
+
if (typeof stableInput === "string") {
|
|
1140
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1141
|
+
} else if (Array.isArray(stableInput)) {
|
|
1142
|
+
const textureArray = mappedTextures;
|
|
1143
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1144
|
+
} else if (IsObject(stableInput)) {
|
|
1145
|
+
const textureRecord = mappedTextures;
|
|
1146
|
+
for (const key in stableInput) {
|
|
1147
|
+
const url = stableInput[key];
|
|
1148
|
+
urlTextureMap.push([url, textureRecord[key]]);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
store.setState((state) => {
|
|
1152
|
+
const refs = new Map(state._textureRefs);
|
|
1153
|
+
let textures = state.textures;
|
|
1154
|
+
let added = false;
|
|
1155
|
+
for (const [url, texture] of urlTextureMap) {
|
|
1156
|
+
if (!textures.has(url)) {
|
|
1157
|
+
if (!added) {
|
|
1158
|
+
textures = new Map(textures);
|
|
1159
|
+
added = true;
|
|
1160
|
+
}
|
|
1161
|
+
textures.set(url, texture);
|
|
1162
|
+
}
|
|
1163
|
+
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
1164
|
+
}
|
|
1165
|
+
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
1166
|
+
});
|
|
1167
|
+
return () => store.setState((state) => {
|
|
1168
|
+
const refs = new Map(state._textureRefs);
|
|
1169
|
+
for (const [url] of urlTextureMap) {
|
|
1170
|
+
const next = (refs.get(url) ?? 0) - 1;
|
|
1171
|
+
if (next <= 0) refs.delete(url);
|
|
1172
|
+
else refs.set(url, next);
|
|
1173
|
+
}
|
|
1174
|
+
return { _textureRefs: refs };
|
|
1175
|
+
});
|
|
1176
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1177
|
+
return mappedTextures;
|
|
1137
1178
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
const
|
|
1147
|
-
|
|
1148
|
-
};
|
|
1149
|
-
useLoader.loader = getLoader$1;
|
|
1150
|
-
|
|
1151
|
-
function useFrame(callback, priorityOrOptions) {
|
|
1152
|
-
const store = React__namespace.useContext(context);
|
|
1153
|
-
const isInsideCanvas = store !== null;
|
|
1154
|
-
const scheduler$1 = scheduler.getScheduler();
|
|
1155
|
-
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
1156
|
-
id: priorityOrOptions.id,
|
|
1157
|
-
phase: priorityOrOptions.phase,
|
|
1158
|
-
priority: priorityOrOptions.priority,
|
|
1159
|
-
fps: priorityOrOptions.fps,
|
|
1160
|
-
drop: priorityOrOptions.drop,
|
|
1161
|
-
enabled: priorityOrOptions.enabled,
|
|
1162
|
-
before: priorityOrOptions.before,
|
|
1163
|
-
after: priorityOrOptions.after
|
|
1164
|
-
}) : "";
|
|
1165
|
-
const options = React__namespace.useMemo(() => {
|
|
1166
|
-
return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
|
|
1167
|
-
}, [optionsKey]);
|
|
1168
|
-
const reactId = React__namespace.useId();
|
|
1169
|
-
const id = options.id ?? reactId;
|
|
1170
|
-
const callbackRef = useMutableCallback(callback);
|
|
1171
|
-
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
1172
|
-
useIsomorphicLayoutEffect(() => {
|
|
1173
|
-
if (!callback) return;
|
|
1174
|
-
if (isInsideCanvas) {
|
|
1175
|
-
const state = store.getState();
|
|
1176
|
-
const rootId = state.internal.rootId;
|
|
1177
|
-
if (isLegacyPriority) {
|
|
1178
|
-
state.internal.priority++;
|
|
1179
|
-
let parentRoot = state.previousRoot;
|
|
1180
|
-
while (parentRoot) {
|
|
1181
|
-
const parentState = parentRoot.getState();
|
|
1182
|
-
if (parentState?.internal) parentState.internal.priority++;
|
|
1183
|
-
parentRoot = parentState?.previousRoot;
|
|
1184
|
-
}
|
|
1185
|
-
notifyDepreciated({
|
|
1186
|
-
heading: "useFrame with numeric priority is deprecated",
|
|
1187
|
-
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 })',
|
|
1188
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1189
|
-
});
|
|
1190
|
-
}
|
|
1191
|
-
const wrappedCallback = (frameState, delta) => {
|
|
1192
|
-
const localState = store.getState();
|
|
1193
|
-
const mergedState = {
|
|
1194
|
-
...localState,
|
|
1195
|
-
time: frameState.time,
|
|
1196
|
-
delta: frameState.delta,
|
|
1197
|
-
elapsed: frameState.elapsed,
|
|
1198
|
-
frame: frameState.frame
|
|
1199
|
-
};
|
|
1200
|
-
callbackRef.current?.(mergedState, delta);
|
|
1201
|
-
};
|
|
1202
|
-
const unregister = scheduler$1.register(wrappedCallback, {
|
|
1203
|
-
id,
|
|
1204
|
-
rootId,
|
|
1205
|
-
...options
|
|
1206
|
-
});
|
|
1207
|
-
return () => {
|
|
1208
|
-
unregister();
|
|
1209
|
-
if (isLegacyPriority) {
|
|
1210
|
-
const currentState = store.getState();
|
|
1211
|
-
if (currentState.internal) {
|
|
1212
|
-
currentState.internal.priority--;
|
|
1213
|
-
let parentRoot = currentState.previousRoot;
|
|
1214
|
-
while (parentRoot) {
|
|
1215
|
-
const parentState = parentRoot.getState();
|
|
1216
|
-
if (parentState?.internal) parentState.internal.priority--;
|
|
1217
|
-
parentRoot = parentState?.previousRoot;
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
};
|
|
1222
|
-
} else {
|
|
1223
|
-
return scheduler$1.register(
|
|
1224
|
-
(state, delta) => {
|
|
1225
|
-
const frameState = state;
|
|
1226
|
-
if (!frameState.renderer) return;
|
|
1227
|
-
callbackRef.current?.(frameState, delta);
|
|
1228
|
-
},
|
|
1229
|
-
{ id, ...options }
|
|
1230
|
-
);
|
|
1231
|
-
}
|
|
1232
|
-
}, [store, scheduler$1, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
1233
|
-
const isPaused = React__namespace.useSyncExternalStore(
|
|
1234
|
-
// Subscribe function
|
|
1235
|
-
React__namespace.useCallback(
|
|
1236
|
-
(onStoreChange) => {
|
|
1237
|
-
return scheduler.getScheduler().subscribeJobState(id, onStoreChange);
|
|
1238
|
-
},
|
|
1239
|
-
[id]
|
|
1240
|
-
),
|
|
1241
|
-
// getSnapshot function
|
|
1242
|
-
React__namespace.useCallback(() => scheduler.getScheduler().isJobPaused(id), [id]),
|
|
1243
|
-
// getServerSnapshot function (SSR)
|
|
1244
|
-
React__namespace.useCallback(() => false, [])
|
|
1245
|
-
);
|
|
1246
|
-
const controls = React__namespace.useMemo(() => {
|
|
1247
|
-
const scheduler2 = scheduler.getScheduler();
|
|
1248
|
-
return {
|
|
1249
|
-
/** The job's unique ID */
|
|
1250
|
-
id,
|
|
1251
|
-
/**
|
|
1252
|
-
* Access to the global scheduler for frame loop control.
|
|
1253
|
-
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1254
|
-
*/
|
|
1255
|
-
scheduler: scheduler2,
|
|
1256
|
-
/**
|
|
1257
|
-
* Manually step this job only.
|
|
1258
|
-
* Bypasses FPS limiting - always runs.
|
|
1259
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1260
|
-
*/
|
|
1261
|
-
step: (timestamp) => {
|
|
1262
|
-
scheduler.getScheduler().stepJob(id, timestamp);
|
|
1263
|
-
},
|
|
1264
|
-
/**
|
|
1265
|
-
* Manually step ALL jobs in the scheduler.
|
|
1266
|
-
* Useful for frameloop='never' mode.
|
|
1267
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1268
|
-
*/
|
|
1269
|
-
stepAll: (timestamp) => {
|
|
1270
|
-
scheduler.getScheduler().step(timestamp);
|
|
1271
|
-
},
|
|
1272
|
-
/**
|
|
1273
|
-
* Pause this job (set enabled=false).
|
|
1274
|
-
* Job remains registered but won't run.
|
|
1275
|
-
*/
|
|
1276
|
-
pause: () => {
|
|
1277
|
-
scheduler.getScheduler().pauseJob(id);
|
|
1278
|
-
},
|
|
1279
|
-
/**
|
|
1280
|
-
* Resume this job (set enabled=true).
|
|
1281
|
-
*/
|
|
1282
|
-
resume: () => {
|
|
1283
|
-
scheduler.getScheduler().resumeJob(id);
|
|
1284
|
-
},
|
|
1285
|
-
/**
|
|
1286
|
-
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1287
|
-
* No need for forceUpdate() in your components.
|
|
1288
|
-
*/
|
|
1289
|
-
isPaused
|
|
1290
|
-
};
|
|
1291
|
-
}, [id, isPaused]);
|
|
1292
|
-
return controls;
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1296
|
-
function getUrls(input) {
|
|
1297
|
-
if (typeof input === "string") return [input];
|
|
1298
|
-
if (Array.isArray(input)) return input;
|
|
1299
|
-
return Object.values(input);
|
|
1300
|
-
}
|
|
1301
|
-
function allUrlsCached(urls, textureCache) {
|
|
1302
|
-
return urls.every((url) => textureCache.has(url));
|
|
1303
|
-
}
|
|
1304
|
-
function buildFromCache(input, textureCache) {
|
|
1305
|
-
if (typeof input === "string") {
|
|
1306
|
-
return textureCache.get(input);
|
|
1307
|
-
} else if (Array.isArray(input)) {
|
|
1308
|
-
return input.map((url) => textureCache.get(url));
|
|
1309
|
-
} else {
|
|
1310
|
-
const result = {};
|
|
1311
|
-
const objInput = input;
|
|
1312
|
-
for (const key in objInput) {
|
|
1313
|
-
result[key] = textureCache.get(objInput[key]);
|
|
1314
|
-
}
|
|
1315
|
-
return result;
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
function useTexture(input, optionsOrOnLoad) {
|
|
1319
|
-
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1320
|
-
const store = useStore();
|
|
1321
|
-
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1322
|
-
const { onLoad, cache = true } = options;
|
|
1323
|
-
const onLoadRef = React.useRef(onLoad);
|
|
1324
|
-
onLoadRef.current = onLoad;
|
|
1325
|
-
const onLoadCalledForRef = React.useRef(null);
|
|
1326
|
-
const urls = React.useMemo(() => getUrls(input), [input]);
|
|
1327
|
-
const cachedResult = React.useMemo(() => {
|
|
1328
|
-
if (!cache) return null;
|
|
1329
|
-
const textures = store.getState().textures;
|
|
1330
|
-
if (!allUrlsCached(urls, textures)) return null;
|
|
1331
|
-
return buildFromCache(input, textures);
|
|
1332
|
-
}, [cache, urls, input, store]);
|
|
1333
|
-
const loadedTextures = useLoader(
|
|
1334
|
-
webgpu.TextureLoader,
|
|
1335
|
-
IsObject(input) ? Object.values(input) : input
|
|
1336
|
-
);
|
|
1337
|
-
const inputKey = urls.join("\0");
|
|
1338
|
-
React.useLayoutEffect(() => {
|
|
1339
|
-
if (cachedResult) return;
|
|
1340
|
-
if (onLoadCalledForRef.current === inputKey) return;
|
|
1341
|
-
onLoadCalledForRef.current = inputKey;
|
|
1342
|
-
onLoadRef.current?.(loadedTextures);
|
|
1343
|
-
}, [cachedResult, loadedTextures, inputKey]);
|
|
1344
|
-
React.useEffect(() => {
|
|
1345
|
-
if (cachedResult) return;
|
|
1346
|
-
if ("initTexture" in renderer) {
|
|
1347
|
-
let textureArray = [];
|
|
1348
|
-
if (Array.isArray(loadedTextures)) {
|
|
1349
|
-
textureArray = loadedTextures;
|
|
1350
|
-
} else if (loadedTextures instanceof webgpu.Texture) {
|
|
1351
|
-
textureArray = [loadedTextures];
|
|
1352
|
-
} else if (IsObject(loadedTextures)) {
|
|
1353
|
-
textureArray = Object.values(loadedTextures);
|
|
1354
|
-
}
|
|
1355
|
-
textureArray.forEach((texture) => {
|
|
1356
|
-
if (texture instanceof webgpu.Texture) {
|
|
1357
|
-
renderer.initTexture(texture);
|
|
1358
|
-
}
|
|
1359
|
-
});
|
|
1360
|
-
}
|
|
1361
|
-
}, [renderer, loadedTextures, cachedResult]);
|
|
1362
|
-
const mappedTextures = React.useMemo(() => {
|
|
1363
|
-
if (cachedResult) return cachedResult;
|
|
1364
|
-
if (IsObject(input)) {
|
|
1365
|
-
const keyed = {};
|
|
1366
|
-
const textureArray = loadedTextures;
|
|
1367
|
-
let i = 0;
|
|
1368
|
-
for (const key in input) keyed[key] = textureArray[i++];
|
|
1369
|
-
return keyed;
|
|
1370
|
-
} else {
|
|
1371
|
-
return loadedTextures;
|
|
1372
|
-
}
|
|
1373
|
-
}, [input, loadedTextures, cachedResult]);
|
|
1374
|
-
React.useEffect(() => {
|
|
1375
|
-
if (!cache) return;
|
|
1376
|
-
const urlTextureMap = [];
|
|
1377
|
-
if (typeof input === "string") {
|
|
1378
|
-
urlTextureMap.push([input, mappedTextures]);
|
|
1379
|
-
} else if (Array.isArray(input)) {
|
|
1380
|
-
const textureArray = mappedTextures;
|
|
1381
|
-
input.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1382
|
-
} else if (IsObject(input)) {
|
|
1383
|
-
const textureRecord = mappedTextures;
|
|
1384
|
-
for (const key in input) {
|
|
1385
|
-
const url = input[key];
|
|
1386
|
-
urlTextureMap.push([url, textureRecord[key]]);
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
store.setState((state) => {
|
|
1390
|
-
const refs = new Map(state._textureRefs);
|
|
1391
|
-
let textures = state.textures;
|
|
1392
|
-
let added = false;
|
|
1393
|
-
for (const [url, texture] of urlTextureMap) {
|
|
1394
|
-
if (!textures.has(url)) {
|
|
1395
|
-
if (!added) {
|
|
1396
|
-
textures = new Map(textures);
|
|
1397
|
-
added = true;
|
|
1398
|
-
}
|
|
1399
|
-
textures.set(url, texture);
|
|
1400
|
-
}
|
|
1401
|
-
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
1402
|
-
}
|
|
1403
|
-
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
1404
|
-
});
|
|
1405
|
-
return () => store.setState((state) => {
|
|
1406
|
-
const refs = new Map(state._textureRefs);
|
|
1407
|
-
for (const [url] of urlTextureMap) {
|
|
1408
|
-
const next = (refs.get(url) ?? 0) - 1;
|
|
1409
|
-
if (next <= 0) refs.delete(url);
|
|
1410
|
-
else refs.set(url, next);
|
|
1411
|
-
}
|
|
1412
|
-
return { _textureRefs: refs };
|
|
1413
|
-
});
|
|
1414
|
-
}, [cache, input, mappedTextures, store]);
|
|
1415
|
-
return mappedTextures;
|
|
1416
|
-
}
|
|
1417
|
-
useTexture.preload = (url) => useLoader.preload(webgpu.TextureLoader, url);
|
|
1418
|
-
useTexture.clear = (input) => useLoader.clear(webgpu.TextureLoader, input);
|
|
1419
|
-
const Texture = ({
|
|
1420
|
-
children,
|
|
1421
|
-
input,
|
|
1422
|
-
onLoad,
|
|
1423
|
-
cache
|
|
1424
|
-
}) => {
|
|
1425
|
-
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1426
|
-
const ret = useTexture(input, options);
|
|
1427
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children?.(ret) });
|
|
1179
|
+
useTexture.preload = (url) => useLoader.preload(webgpu.TextureLoader, url);
|
|
1180
|
+
useTexture.clear = (input) => useLoader.clear(webgpu.TextureLoader, input);
|
|
1181
|
+
const Texture = ({
|
|
1182
|
+
children,
|
|
1183
|
+
input,
|
|
1184
|
+
onLoad,
|
|
1185
|
+
cache
|
|
1186
|
+
}) => {
|
|
1187
|
+
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1188
|
+
const ret = useTexture(input, options);
|
|
1189
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children?.(ret) });
|
|
1428
1190
|
};
|
|
1429
1191
|
|
|
1430
1192
|
function useTextures(selector) {
|
|
@@ -1574,7 +1336,7 @@ function useEnvironment({
|
|
|
1574
1336
|
texture = texture.renderTarget?.texture;
|
|
1575
1337
|
}
|
|
1576
1338
|
texture.mapping = isCubemap ? webgpu.CubeReflectionMapping : webgpu.EquirectangularReflectionMapping;
|
|
1577
|
-
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
1339
|
+
texture.colorSpace = colorSpace ?? (isCubemap && extension !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
1578
1340
|
return texture;
|
|
1579
1341
|
}
|
|
1580
1342
|
const preloadDefaultOptions = {
|
|
@@ -1627,22 +1389,15 @@ function getExtension(files) {
|
|
|
1627
1389
|
const isCubemap = isArray(files) && files.length === 6;
|
|
1628
1390
|
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
1629
1391
|
const firstEntry = isArray(files) ? files[0] : files;
|
|
1630
|
-
const
|
|
1392
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1393
|
+
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;
|
|
1631
1394
|
return { extension, isCubemap, isGainmap };
|
|
1632
1395
|
}
|
|
1633
1396
|
function getLoader(extension) {
|
|
1634
|
-
const loader = extension === "cube" ? webgpu.CubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
|
|
1397
|
+
const loader = extension === "cube" ? webgpu.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;
|
|
1635
1398
|
return loader;
|
|
1636
1399
|
}
|
|
1637
1400
|
|
|
1638
|
-
function useStore() {
|
|
1639
|
-
const store = React.useContext(context);
|
|
1640
|
-
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1641
|
-
return store;
|
|
1642
|
-
}
|
|
1643
|
-
function useThree(selector = (state) => state, equalityFn) {
|
|
1644
|
-
return useStore()(selector, equalityFn);
|
|
1645
|
-
}
|
|
1646
1401
|
function useInstanceHandle(ref) {
|
|
1647
1402
|
const instance = React.useRef(null);
|
|
1648
1403
|
React.useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
@@ -1682,13 +1437,19 @@ function addTail(callback) {
|
|
|
1682
1437
|
return scheduler.getScheduler().onIdle(callback);
|
|
1683
1438
|
}
|
|
1684
1439
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1685
|
-
|
|
1440
|
+
const rootId = state?.internal?.rootId;
|
|
1441
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1442
|
+
if (rootId) scheduler$1.invalidateRoot(rootId, frames, stackFrames);
|
|
1443
|
+
else scheduler$1.invalidate(frames, stackFrames);
|
|
1686
1444
|
}
|
|
1687
|
-
function advance(timestamp) {
|
|
1688
|
-
|
|
1445
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1446
|
+
const rootId = state?.internal?.rootId;
|
|
1447
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1448
|
+
if (rootId) scheduler$1.stepRoot(rootId, timestamp);
|
|
1449
|
+
else scheduler$1.step(timestamp);
|
|
1689
1450
|
}
|
|
1690
1451
|
|
|
1691
|
-
const version = "10.0.0-alpha.
|
|
1452
|
+
const version = "10.0.0-alpha.5";
|
|
1692
1453
|
const packageData = {
|
|
1693
1454
|
version: version};
|
|
1694
1455
|
|
|
@@ -13547,7 +13308,10 @@ function extend(objects) {
|
|
|
13547
13308
|
catalogue[Component] = objects;
|
|
13548
13309
|
return Component;
|
|
13549
13310
|
} else {
|
|
13550
|
-
|
|
13311
|
+
for (const name in objects) {
|
|
13312
|
+
const object = objects[name];
|
|
13313
|
+
if (isConstructor(object)) catalogue[name] = object;
|
|
13314
|
+
}
|
|
13551
13315
|
}
|
|
13552
13316
|
}
|
|
13553
13317
|
function validateInstance(type, props) {
|
|
@@ -13895,7 +13659,7 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13895
13659
|
getRootHostContext: () => NO_CONTEXT,
|
|
13896
13660
|
getChildHostContext: () => NO_CONTEXT,
|
|
13897
13661
|
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
13898
|
-
validateInstance(type, newProps);
|
|
13662
|
+
validateInstance(instance.type, newProps);
|
|
13899
13663
|
let reconstruct = false;
|
|
13900
13664
|
if (instance.type === "primitive" && oldProps.object !== newProps.object) reconstruct = true;
|
|
13901
13665
|
else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
|
|
@@ -13910,162 +13674,491 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13910
13674
|
else delete instance.props.attach;
|
|
13911
13675
|
if (Object.keys(changedProps).length) applyProps(instance.object, changedProps);
|
|
13912
13676
|
}
|
|
13913
|
-
},
|
|
13914
|
-
finalizeInitialChildren: (instance) => {
|
|
13915
|
-
for (const prop in instance.props) {
|
|
13916
|
-
if (isFromRef(instance.props[prop])) return true;
|
|
13677
|
+
},
|
|
13678
|
+
finalizeInitialChildren: (instance) => {
|
|
13679
|
+
for (const prop in instance.props) {
|
|
13680
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
13681
|
+
}
|
|
13682
|
+
return false;
|
|
13683
|
+
},
|
|
13684
|
+
commitMount(instance) {
|
|
13685
|
+
const resolved = {};
|
|
13686
|
+
for (const prop in instance.props) {
|
|
13687
|
+
const value = instance.props[prop];
|
|
13688
|
+
if (isFromRef(value)) {
|
|
13689
|
+
const { [FROM_REF]: ref, transform } = value;
|
|
13690
|
+
if (ref.current != null) resolved[prop] = transform ? transform(ref.current) : ref.current;
|
|
13691
|
+
}
|
|
13692
|
+
}
|
|
13693
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
13694
|
+
},
|
|
13695
|
+
getPublicInstance: (instance) => instance?.object,
|
|
13696
|
+
prepareForCommit: () => null,
|
|
13697
|
+
preparePortalMount: (container) => {
|
|
13698
|
+
const target = container.getState().internal.container ?? container.getState().scene;
|
|
13699
|
+
return prepare(target, container, "", {});
|
|
13700
|
+
},
|
|
13701
|
+
// Reconstructed instances are swapped once all mutations are committed,
|
|
13702
|
+
// before layout effects run so refs point to the new objects
|
|
13703
|
+
resetAfterCommit: flushReconstructedInstances,
|
|
13704
|
+
shouldSetTextContent: () => false,
|
|
13705
|
+
clearContainer: () => false,
|
|
13706
|
+
hideInstance,
|
|
13707
|
+
unhideInstance,
|
|
13708
|
+
createTextInstance: handleTextInstance,
|
|
13709
|
+
hideTextInstance: handleTextInstance,
|
|
13710
|
+
unhideTextInstance: handleTextInstance,
|
|
13711
|
+
// Mirrors react-dom, which flushes discrete work in microtasks
|
|
13712
|
+
supportsMicrotasks: true,
|
|
13713
|
+
scheduleMicrotask,
|
|
13714
|
+
scheduleTimeout: typeof setTimeout === "function" ? setTimeout : void 0,
|
|
13715
|
+
cancelTimeout: typeof clearTimeout === "function" ? clearTimeout : void 0,
|
|
13716
|
+
noTimeout: -1,
|
|
13717
|
+
getInstanceFromNode: () => null,
|
|
13718
|
+
beforeActiveInstanceBlur() {
|
|
13719
|
+
},
|
|
13720
|
+
afterActiveInstanceBlur() {
|
|
13721
|
+
},
|
|
13722
|
+
detachDeletedInstance() {
|
|
13723
|
+
},
|
|
13724
|
+
prepareScopeUpdate() {
|
|
13725
|
+
},
|
|
13726
|
+
getInstanceFromScope: () => null,
|
|
13727
|
+
shouldAttemptEagerTransition: () => false,
|
|
13728
|
+
trackSchedulerEvent: () => {
|
|
13729
|
+
},
|
|
13730
|
+
resolveEventType: () => null,
|
|
13731
|
+
resolveEventTimeStamp: () => -1.1,
|
|
13732
|
+
requestPostPaintCallback() {
|
|
13733
|
+
},
|
|
13734
|
+
maySuspendCommit: () => false,
|
|
13735
|
+
preloadInstance: () => true,
|
|
13736
|
+
// true indicates already loaded
|
|
13737
|
+
suspendInstance() {
|
|
13738
|
+
},
|
|
13739
|
+
waitForCommitToBeReady: () => null,
|
|
13740
|
+
NotPendingTransition: null,
|
|
13741
|
+
// The reconciler types use the internal ReactContext with all the hidden properties
|
|
13742
|
+
// so we have to cast from the public React.Context type
|
|
13743
|
+
HostTransitionContext: /* @__PURE__ */ React__namespace.createContext(
|
|
13744
|
+
null
|
|
13745
|
+
),
|
|
13746
|
+
setCurrentUpdatePriority(newPriority) {
|
|
13747
|
+
currentUpdatePriority = newPriority;
|
|
13748
|
+
},
|
|
13749
|
+
getCurrentUpdatePriority() {
|
|
13750
|
+
return currentUpdatePriority;
|
|
13751
|
+
},
|
|
13752
|
+
resolveUpdatePriority() {
|
|
13753
|
+
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13754
|
+
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13755
|
+
if (eventType === void 0) return r;
|
|
13756
|
+
return getEventPriority(eventType);
|
|
13757
|
+
},
|
|
13758
|
+
resetFormInstance() {
|
|
13759
|
+
},
|
|
13760
|
+
// @ts-ignore DefinitelyTyped is not up to date
|
|
13761
|
+
rendererPackageName: "@react-three/fiber",
|
|
13762
|
+
rendererVersion: packageData.version,
|
|
13763
|
+
// 19.2 Reconciler
|
|
13764
|
+
// https://github.com/facebook/react/pull/31975
|
|
13765
|
+
// https://github.com/facebook/react/pull/31999
|
|
13766
|
+
applyViewTransitionName(_instance, _name, _className) {
|
|
13767
|
+
},
|
|
13768
|
+
restoreViewTransitionName(_instance, _props) {
|
|
13769
|
+
},
|
|
13770
|
+
cancelViewTransitionName(_instance, _name, _props) {
|
|
13771
|
+
},
|
|
13772
|
+
cancelRootViewTransitionName(_rootContainer) {
|
|
13773
|
+
},
|
|
13774
|
+
restoreRootViewTransitionName(_rootContainer) {
|
|
13775
|
+
},
|
|
13776
|
+
InstanceMeasurement: null,
|
|
13777
|
+
measureInstance: (_instance) => null,
|
|
13778
|
+
wasInstanceInViewport: (_measurement) => true,
|
|
13779
|
+
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
13780
|
+
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
13781
|
+
// https://github.com/facebook/react/pull/32002
|
|
13782
|
+
// https://github.com/facebook/react/pull/34486
|
|
13783
|
+
suspendOnActiveViewTransition(_state, _container) {
|
|
13784
|
+
},
|
|
13785
|
+
// https://github.com/facebook/react/pull/32451
|
|
13786
|
+
// https://github.com/facebook/react/pull/32760
|
|
13787
|
+
startGestureTransition: () => null,
|
|
13788
|
+
startViewTransition: () => null,
|
|
13789
|
+
stopViewTransition(_transition) {
|
|
13790
|
+
},
|
|
13791
|
+
// https://github.com/facebook/react/pull/32038
|
|
13792
|
+
createViewTransitionInstance: (_name) => null,
|
|
13793
|
+
// https://github.com/facebook/react/pull/32379
|
|
13794
|
+
// https://github.com/facebook/react/pull/32786
|
|
13795
|
+
getCurrentGestureOffset(_provider) {
|
|
13796
|
+
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
13797
|
+
},
|
|
13798
|
+
// https://github.com/facebook/react/pull/32500
|
|
13799
|
+
cloneMutableInstance(instance, _keepChildren) {
|
|
13800
|
+
return instance;
|
|
13801
|
+
},
|
|
13802
|
+
cloneMutableTextInstance(textInstance) {
|
|
13803
|
+
return textInstance;
|
|
13804
|
+
},
|
|
13805
|
+
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
13806
|
+
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
13807
|
+
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
13808
|
+
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
13809
|
+
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
13810
|
+
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
13811
|
+
cloneRootViewTransitionContainer(_rootContainer) {
|
|
13812
|
+
},
|
|
13813
|
+
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
13814
|
+
},
|
|
13815
|
+
// https://github.com/facebook/react/pull/32465
|
|
13816
|
+
createFragmentInstance: (_fiber) => null,
|
|
13817
|
+
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
13818
|
+
},
|
|
13819
|
+
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
13820
|
+
},
|
|
13821
|
+
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
13822
|
+
},
|
|
13823
|
+
// https://github.com/facebook/react/pull/32653
|
|
13824
|
+
measureClonedInstance: (_instance) => null,
|
|
13825
|
+
// https://github.com/facebook/react/pull/32819
|
|
13826
|
+
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
13827
|
+
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
13828
|
+
// https://github.com/facebook/react/pull/34486
|
|
13829
|
+
startSuspendingCommit: () => null,
|
|
13830
|
+
// https://github.com/facebook/react/pull/34522
|
|
13831
|
+
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
13832
|
+
});
|
|
13833
|
+
|
|
13834
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
13835
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
13836
|
+
if (!stack) return false;
|
|
13837
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
13838
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
13839
|
+
}
|
|
13840
|
+
|
|
13841
|
+
const createStore = (invalidate, advance) => {
|
|
13842
|
+
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
13843
|
+
const position = new webgpu.Vector3();
|
|
13844
|
+
const defaultTarget = new webgpu.Vector3();
|
|
13845
|
+
const tempTarget = new webgpu.Vector3();
|
|
13846
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
13847
|
+
const { width, height, top, left } = size;
|
|
13848
|
+
const aspect = width / height;
|
|
13849
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
13850
|
+
else tempTarget.set(...target);
|
|
13851
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
13852
|
+
if (isOrthographicCamera(camera)) {
|
|
13853
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
13854
|
+
} else {
|
|
13855
|
+
const fov = camera.fov * Math.PI / 180;
|
|
13856
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
13857
|
+
const w = h * (width / height);
|
|
13858
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
13859
|
+
}
|
|
13860
|
+
}
|
|
13861
|
+
let performanceTimeout = void 0;
|
|
13862
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
13863
|
+
const pointer = new webgpu.Vector2();
|
|
13864
|
+
const rootState = {
|
|
13865
|
+
set,
|
|
13866
|
+
get,
|
|
13867
|
+
// Mock objects that have to be configured
|
|
13868
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
13869
|
+
primaryStore: null,
|
|
13870
|
+
gl: null,
|
|
13871
|
+
renderer: null,
|
|
13872
|
+
camera: null,
|
|
13873
|
+
frustum: new webgpu.Frustum(),
|
|
13874
|
+
autoUpdateFrustum: true,
|
|
13875
|
+
raycaster: null,
|
|
13876
|
+
events: {
|
|
13877
|
+
priority: 1,
|
|
13878
|
+
enabled: true,
|
|
13879
|
+
connected: false,
|
|
13880
|
+
frameTimedRaycasts: true,
|
|
13881
|
+
alwaysFireOnScroll: true,
|
|
13882
|
+
updateOnFrame: false
|
|
13883
|
+
},
|
|
13884
|
+
scene: null,
|
|
13885
|
+
rootScene: null,
|
|
13886
|
+
xr: null,
|
|
13887
|
+
inspector: null,
|
|
13888
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
13889
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
13890
|
+
textureColorSpace: webgpu.SRGBColorSpace,
|
|
13891
|
+
isLegacy: false,
|
|
13892
|
+
webGPUSupported: false,
|
|
13893
|
+
isNative: false,
|
|
13894
|
+
controls: null,
|
|
13895
|
+
pointer,
|
|
13896
|
+
mouse: pointer,
|
|
13897
|
+
frameloop: "always",
|
|
13898
|
+
onPointerMissed: void 0,
|
|
13899
|
+
onDragOverMissed: void 0,
|
|
13900
|
+
onDropMissed: void 0,
|
|
13901
|
+
performance: {
|
|
13902
|
+
current: 1,
|
|
13903
|
+
min: 0.5,
|
|
13904
|
+
max: 1,
|
|
13905
|
+
debounce: 200,
|
|
13906
|
+
regress: () => {
|
|
13907
|
+
const state2 = get();
|
|
13908
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
13909
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
13910
|
+
performanceTimeout = setTimeout(
|
|
13911
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
13912
|
+
state2.performance.debounce
|
|
13913
|
+
);
|
|
13914
|
+
}
|
|
13915
|
+
},
|
|
13916
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
13917
|
+
viewport: {
|
|
13918
|
+
initialDpr: 0,
|
|
13919
|
+
dpr: 0,
|
|
13920
|
+
width: 0,
|
|
13921
|
+
height: 0,
|
|
13922
|
+
top: 0,
|
|
13923
|
+
left: 0,
|
|
13924
|
+
aspect: 0,
|
|
13925
|
+
distance: 0,
|
|
13926
|
+
factor: 0,
|
|
13927
|
+
getCurrentViewport
|
|
13928
|
+
},
|
|
13929
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
13930
|
+
setSize: (width, height, top, left) => {
|
|
13931
|
+
const state2 = get();
|
|
13932
|
+
if (width === void 0) {
|
|
13933
|
+
set({ _sizeImperative: false });
|
|
13934
|
+
if (state2._sizeProps) {
|
|
13935
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
13936
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
13937
|
+
const currentSize = state2.size;
|
|
13938
|
+
const newSize = {
|
|
13939
|
+
width: propW ?? currentSize.width,
|
|
13940
|
+
height: propH ?? currentSize.height,
|
|
13941
|
+
top: currentSize.top,
|
|
13942
|
+
left: currentSize.left
|
|
13943
|
+
};
|
|
13944
|
+
set((s) => ({
|
|
13945
|
+
size: newSize,
|
|
13946
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
13947
|
+
}));
|
|
13948
|
+
get().invalidate();
|
|
13949
|
+
}
|
|
13950
|
+
}
|
|
13951
|
+
return;
|
|
13952
|
+
}
|
|
13953
|
+
const w = width;
|
|
13954
|
+
const h = height ?? width;
|
|
13955
|
+
const t = top ?? state2.size.top;
|
|
13956
|
+
const l = left ?? state2.size.left;
|
|
13957
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
13958
|
+
set((s) => ({
|
|
13959
|
+
size,
|
|
13960
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
13961
|
+
_sizeImperative: true
|
|
13962
|
+
}));
|
|
13963
|
+
get().invalidate();
|
|
13964
|
+
},
|
|
13965
|
+
setDpr: (dpr) => set((state2) => {
|
|
13966
|
+
const resolved = calculateDpr(dpr);
|
|
13967
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
13968
|
+
}),
|
|
13969
|
+
setFrameloop: (frameloop = "always") => {
|
|
13970
|
+
const rootId = get().internal.rootId;
|
|
13971
|
+
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
13972
|
+
set(() => ({ frameloop }));
|
|
13973
|
+
},
|
|
13974
|
+
setError: (error) => set(() => ({ error })),
|
|
13975
|
+
error: null,
|
|
13976
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
13977
|
+
uniforms: {},
|
|
13978
|
+
nodes: {},
|
|
13979
|
+
buffers: {},
|
|
13980
|
+
gpuStorage: {},
|
|
13981
|
+
textures: /* @__PURE__ */ new Map(),
|
|
13982
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
13983
|
+
renderPipeline: null,
|
|
13984
|
+
passes: {},
|
|
13985
|
+
_hmrVersion: 0,
|
|
13986
|
+
_sizeImperative: false,
|
|
13987
|
+
_sizeProps: null,
|
|
13988
|
+
previousRoot: void 0,
|
|
13989
|
+
internal: {
|
|
13990
|
+
// Events
|
|
13991
|
+
interaction: [],
|
|
13992
|
+
subscribers: [],
|
|
13993
|
+
// Per-pointer state (new unified structure)
|
|
13994
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
13995
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
13996
|
+
lastEvent: React__namespace.createRef(),
|
|
13997
|
+
// Deprecated but kept for backwards compatibility
|
|
13998
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
13999
|
+
initialClick: [0, 0],
|
|
14000
|
+
initialHits: [],
|
|
14001
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
14002
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
14003
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
14004
|
+
// Occlusion system (WebGPU only)
|
|
14005
|
+
occlusionEnabled: false,
|
|
14006
|
+
occlusionObserver: null,
|
|
14007
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
14008
|
+
helperGroup: null,
|
|
14009
|
+
// Updates
|
|
14010
|
+
active: false,
|
|
14011
|
+
frames: 0,
|
|
14012
|
+
priority: 0,
|
|
14013
|
+
subscribe: (ref, priority, store) => {
|
|
14014
|
+
const internal = get().internal;
|
|
14015
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
14016
|
+
internal.subscribers.push({ ref, priority, store });
|
|
14017
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14018
|
+
return () => {
|
|
14019
|
+
const internal2 = get().internal;
|
|
14020
|
+
if (internal2?.subscribers) {
|
|
14021
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14022
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14023
|
+
}
|
|
14024
|
+
};
|
|
14025
|
+
},
|
|
14026
|
+
// Renderer Storage (single source of truth)
|
|
14027
|
+
actualRenderer: null,
|
|
14028
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14029
|
+
scheduler: null,
|
|
14030
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
14031
|
+
renderOverride: null
|
|
14032
|
+
}
|
|
14033
|
+
};
|
|
14034
|
+
return rootState;
|
|
14035
|
+
});
|
|
14036
|
+
const state = rootStore.getState();
|
|
14037
|
+
Object.defineProperty(state, "gl", {
|
|
14038
|
+
get() {
|
|
14039
|
+
const currentState = rootStore.getState();
|
|
14040
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14041
|
+
const stack = new Error().stack || "";
|
|
14042
|
+
if (!isInternalRendererAccess(stack)) {
|
|
14043
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14044
|
+
notifyDepreciated({
|
|
14045
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
14046
|
+
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
|
|
14047
|
+
});
|
|
14048
|
+
}
|
|
14049
|
+
}
|
|
14050
|
+
return currentState.internal.actualRenderer;
|
|
14051
|
+
},
|
|
14052
|
+
set(value) {
|
|
14053
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14054
|
+
},
|
|
14055
|
+
enumerable: true,
|
|
14056
|
+
configurable: true
|
|
14057
|
+
});
|
|
14058
|
+
Object.defineProperty(state, "renderer", {
|
|
14059
|
+
get() {
|
|
14060
|
+
return rootStore.getState().internal.actualRenderer;
|
|
14061
|
+
},
|
|
14062
|
+
set(value) {
|
|
14063
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14064
|
+
},
|
|
14065
|
+
enumerable: true,
|
|
14066
|
+
configurable: true
|
|
14067
|
+
});
|
|
14068
|
+
let oldScene = state.scene;
|
|
14069
|
+
rootStore.subscribe(() => {
|
|
14070
|
+
const currentState = rootStore.getState();
|
|
14071
|
+
const { scene, rootScene, set } = currentState;
|
|
14072
|
+
if (scene !== oldScene) {
|
|
14073
|
+
oldScene = scene;
|
|
14074
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
14075
|
+
set({ rootScene: scene });
|
|
14076
|
+
}
|
|
14077
|
+
}
|
|
14078
|
+
});
|
|
14079
|
+
let oldSize = state.size;
|
|
14080
|
+
let oldDpr = state.viewport.dpr;
|
|
14081
|
+
let oldCamera = state.camera;
|
|
14082
|
+
rootStore.subscribe(() => {
|
|
14083
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14084
|
+
const actualRenderer = internal.actualRenderer;
|
|
14085
|
+
const canvasTarget = internal.canvasTarget;
|
|
14086
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14087
|
+
oldSize = size;
|
|
14088
|
+
oldDpr = viewport.dpr;
|
|
14089
|
+
updateCamera(camera, size);
|
|
14090
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14091
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14092
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
14093
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14094
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
13917
14095
|
}
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
14096
|
+
if (camera !== oldCamera) {
|
|
14097
|
+
oldCamera = camera;
|
|
14098
|
+
const { rootScene } = rootStore.getState();
|
|
14099
|
+
if (camera && rootScene && !camera.parent) {
|
|
14100
|
+
rootScene.add(camera);
|
|
14101
|
+
}
|
|
14102
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14103
|
+
const currentState = rootStore.getState();
|
|
14104
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
14105
|
+
updateFrustum(camera, currentState.frustum);
|
|
13927
14106
|
}
|
|
13928
14107
|
}
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
),
|
|
13982
|
-
|
|
13983
|
-
currentUpdatePriority = newPriority;
|
|
13984
|
-
},
|
|
13985
|
-
getCurrentUpdatePriority() {
|
|
13986
|
-
return currentUpdatePriority;
|
|
13987
|
-
},
|
|
13988
|
-
resolveUpdatePriority() {
|
|
13989
|
-
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13990
|
-
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13991
|
-
if (eventType === void 0) return r;
|
|
13992
|
-
return getEventPriority(eventType);
|
|
13993
|
-
},
|
|
13994
|
-
resetFormInstance() {
|
|
13995
|
-
},
|
|
13996
|
-
// @ts-ignore DefinitelyTyped is not up to date
|
|
13997
|
-
rendererPackageName: "@react-three/fiber",
|
|
13998
|
-
rendererVersion: packageData.version,
|
|
13999
|
-
// 19.2 Reconciler
|
|
14000
|
-
// https://github.com/facebook/react/pull/31975
|
|
14001
|
-
// https://github.com/facebook/react/pull/31999
|
|
14002
|
-
applyViewTransitionName(_instance, _name, _className) {
|
|
14003
|
-
},
|
|
14004
|
-
restoreViewTransitionName(_instance, _props) {
|
|
14005
|
-
},
|
|
14006
|
-
cancelViewTransitionName(_instance, _name, _props) {
|
|
14007
|
-
},
|
|
14008
|
-
cancelRootViewTransitionName(_rootContainer) {
|
|
14009
|
-
},
|
|
14010
|
-
restoreRootViewTransitionName(_rootContainer) {
|
|
14011
|
-
},
|
|
14012
|
-
InstanceMeasurement: null,
|
|
14013
|
-
measureInstance: (_instance) => null,
|
|
14014
|
-
wasInstanceInViewport: (_measurement) => true,
|
|
14015
|
-
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
14016
|
-
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
14017
|
-
// https://github.com/facebook/react/pull/32002
|
|
14018
|
-
// https://github.com/facebook/react/pull/34486
|
|
14019
|
-
suspendOnActiveViewTransition(_state, _container) {
|
|
14020
|
-
},
|
|
14021
|
-
// https://github.com/facebook/react/pull/32451
|
|
14022
|
-
// https://github.com/facebook/react/pull/32760
|
|
14023
|
-
startGestureTransition: () => null,
|
|
14024
|
-
startViewTransition: () => null,
|
|
14025
|
-
stopViewTransition(_transition) {
|
|
14026
|
-
},
|
|
14027
|
-
// https://github.com/facebook/react/pull/32038
|
|
14028
|
-
createViewTransitionInstance: (_name) => null,
|
|
14029
|
-
// https://github.com/facebook/react/pull/32379
|
|
14030
|
-
// https://github.com/facebook/react/pull/32786
|
|
14031
|
-
getCurrentGestureOffset(_provider) {
|
|
14032
|
-
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
14033
|
-
},
|
|
14034
|
-
// https://github.com/facebook/react/pull/32500
|
|
14035
|
-
cloneMutableInstance(instance, _keepChildren) {
|
|
14036
|
-
return instance;
|
|
14037
|
-
},
|
|
14038
|
-
cloneMutableTextInstance(textInstance) {
|
|
14039
|
-
return textInstance;
|
|
14040
|
-
},
|
|
14041
|
-
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
14042
|
-
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
14043
|
-
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
14044
|
-
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
14045
|
-
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
14046
|
-
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
14047
|
-
cloneRootViewTransitionContainer(_rootContainer) {
|
|
14048
|
-
},
|
|
14049
|
-
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
14050
|
-
},
|
|
14051
|
-
// https://github.com/facebook/react/pull/32465
|
|
14052
|
-
createFragmentInstance: (_fiber) => null,
|
|
14053
|
-
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
14054
|
-
},
|
|
14055
|
-
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
14056
|
-
},
|
|
14057
|
-
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
14058
|
-
},
|
|
14059
|
-
// https://github.com/facebook/react/pull/32653
|
|
14060
|
-
measureClonedInstance: (_instance) => null,
|
|
14061
|
-
// https://github.com/facebook/react/pull/32819
|
|
14062
|
-
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
14063
|
-
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
14064
|
-
// https://github.com/facebook/react/pull/34486
|
|
14065
|
-
startSuspendingCommit: () => null,
|
|
14066
|
-
// https://github.com/facebook/react/pull/34522
|
|
14067
|
-
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14068
|
-
});
|
|
14108
|
+
});
|
|
14109
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
14110
|
+
return rootStore;
|
|
14111
|
+
};
|
|
14112
|
+
|
|
14113
|
+
const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
|
|
14114
|
+
function getRegistry() {
|
|
14115
|
+
return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
|
|
14116
|
+
extensions: /* @__PURE__ */ new Map(),
|
|
14117
|
+
roots: /* @__PURE__ */ new Set(),
|
|
14118
|
+
applied: /* @__PURE__ */ new WeakMap()
|
|
14119
|
+
});
|
|
14120
|
+
}
|
|
14121
|
+
function setupRoot(registry, store, extension) {
|
|
14122
|
+
let applied = registry.applied.get(store);
|
|
14123
|
+
if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
|
|
14124
|
+
if (applied.has(extension.name)) return;
|
|
14125
|
+
applied.set(extension.name, extension);
|
|
14126
|
+
const patch = extension.setup?.(store);
|
|
14127
|
+
if (patch) store.setState(patch);
|
|
14128
|
+
}
|
|
14129
|
+
function registerRootExtension(extension) {
|
|
14130
|
+
const registry = getRegistry();
|
|
14131
|
+
registry.extensions.set(extension.name, extension);
|
|
14132
|
+
for (const store of registry.roots) setupRoot(registry, store, extension);
|
|
14133
|
+
return () => {
|
|
14134
|
+
if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
|
|
14135
|
+
};
|
|
14136
|
+
}
|
|
14137
|
+
function setRenderOverride(store, render) {
|
|
14138
|
+
store.getState().internal.renderOverride = render;
|
|
14139
|
+
}
|
|
14140
|
+
function attachRootExtensions(store) {
|
|
14141
|
+
const registry = getRegistry();
|
|
14142
|
+
registry.roots.add(store);
|
|
14143
|
+
for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
|
|
14144
|
+
}
|
|
14145
|
+
function current(registry, setUpBy) {
|
|
14146
|
+
return registry.extensions.get(setUpBy.name) ?? setUpBy;
|
|
14147
|
+
}
|
|
14148
|
+
function detachRootExtensions(store) {
|
|
14149
|
+
const registry = getRegistry();
|
|
14150
|
+
if (!registry.roots.delete(store)) return;
|
|
14151
|
+
const applied = registry.applied.get(store);
|
|
14152
|
+
registry.applied.delete(store);
|
|
14153
|
+
if (!applied) return;
|
|
14154
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
|
|
14155
|
+
}
|
|
14156
|
+
function notifyRootExtensionsHmr(store) {
|
|
14157
|
+
const registry = getRegistry();
|
|
14158
|
+
const applied = registry.applied.get(store);
|
|
14159
|
+
if (!applied) return;
|
|
14160
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
|
|
14161
|
+
}
|
|
14069
14162
|
|
|
14070
14163
|
const isRenderer = (def) => !!def?.render;
|
|
14071
14164
|
const _roots = /* @__PURE__ */ new Map();
|
|
@@ -14222,9 +14315,8 @@ function createRoot(canvas) {
|
|
|
14222
14315
|
if (!renderer.hasInitialized?.()) {
|
|
14223
14316
|
const size2 = computeInitialSize(canvas, propsSize);
|
|
14224
14317
|
if (size2.width > 0 && size2.height > 0) {
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
canvas.height = size2.height * pixelRatio;
|
|
14318
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14319
|
+
renderer.setSize(size2.width, size2.height, false);
|
|
14228
14320
|
}
|
|
14229
14321
|
await renderer.init();
|
|
14230
14322
|
}
|
|
@@ -14233,7 +14325,7 @@ function createRoot(canvas) {
|
|
|
14233
14325
|
state.internal.actualRenderer = renderer;
|
|
14234
14326
|
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14235
14327
|
if (canvasId && !state.internal.isSecondary) {
|
|
14236
|
-
const canvasTarget =
|
|
14328
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14237
14329
|
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14238
14330
|
state.set((prev) => ({
|
|
14239
14331
|
internal: {
|
|
@@ -14347,7 +14439,7 @@ function createRoot(canvas) {
|
|
|
14347
14439
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14348
14440
|
const state2 = store.getState();
|
|
14349
14441
|
if (state2.frameloop === "never") return;
|
|
14350
|
-
advance(timestamp);
|
|
14442
|
+
advance(timestamp, true, state2);
|
|
14351
14443
|
};
|
|
14352
14444
|
const actualRenderer = state.internal.actualRenderer;
|
|
14353
14445
|
const handleSessionChange = () => {
|
|
@@ -14355,7 +14447,7 @@ function createRoot(canvas) {
|
|
|
14355
14447
|
const renderer2 = state2.internal.actualRenderer;
|
|
14356
14448
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14357
14449
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14358
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14450
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14359
14451
|
};
|
|
14360
14452
|
const xr = {
|
|
14361
14453
|
connect() {
|
|
@@ -14437,14 +14529,23 @@ function createRoot(canvas) {
|
|
|
14437
14529
|
const newRootId = canvasId || scheduler$1.generateRootId();
|
|
14438
14530
|
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
14439
14531
|
getState: () => store.getState(),
|
|
14440
|
-
onError: (err) => store.getState().setError(err)
|
|
14532
|
+
onError: (err) => store.getState().setError(err),
|
|
14533
|
+
frameloop: store.getState().frameloop,
|
|
14534
|
+
before: schedulerConfig?.before,
|
|
14535
|
+
after: schedulerConfig?.after,
|
|
14536
|
+
order: schedulerConfig?.order
|
|
14441
14537
|
});
|
|
14442
14538
|
const unregisterCanvasTarget = scheduler$1.register(
|
|
14443
14539
|
() => {
|
|
14444
14540
|
const state2 = store.getState();
|
|
14445
|
-
|
|
14541
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14542
|
+
if (canvasTarget) {
|
|
14446
14543
|
const renderer2 = state2.internal.actualRenderer;
|
|
14447
|
-
renderer2.setCanvasTarget(
|
|
14544
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14545
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14546
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14547
|
+
renderer2.backend?.updateSize?.();
|
|
14548
|
+
}
|
|
14448
14549
|
}
|
|
14449
14550
|
},
|
|
14450
14551
|
{
|
|
@@ -14500,7 +14601,8 @@ function createRoot(canvas) {
|
|
|
14500
14601
|
const userHandlesRender = scheduler$1.hasUserJobsInPhase("render", newRootId);
|
|
14501
14602
|
if (userHandlesRender || state2.internal.priority) return;
|
|
14502
14603
|
try {
|
|
14503
|
-
|
|
14604
|
+
const renderOverride = state2.internal.renderOverride;
|
|
14605
|
+
if (renderOverride) renderOverride();
|
|
14504
14606
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
14505
14607
|
} catch (error) {
|
|
14506
14608
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -14513,8 +14615,7 @@ function createRoot(canvas) {
|
|
|
14513
14615
|
phase: "render",
|
|
14514
14616
|
system: true,
|
|
14515
14617
|
// Internal flag: this is a system job, not user-controlled
|
|
14516
|
-
//
|
|
14517
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14618
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14518
14619
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14519
14620
|
}
|
|
14520
14621
|
);
|
|
@@ -14533,8 +14634,22 @@ function createRoot(canvas) {
|
|
|
14533
14634
|
scheduler: scheduler$1
|
|
14534
14635
|
}
|
|
14535
14636
|
}));
|
|
14637
|
+
} else {
|
|
14638
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14639
|
+
if (constraintsChanged) {
|
|
14640
|
+
scheduler$1.setRootConstraints(rootId, {
|
|
14641
|
+
before: schedulerConfig?.before,
|
|
14642
|
+
after: schedulerConfig?.after
|
|
14643
|
+
});
|
|
14644
|
+
}
|
|
14645
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14646
|
+
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14647
|
+
}
|
|
14536
14648
|
}
|
|
14537
|
-
|
|
14649
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14650
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14651
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14652
|
+
attachRootExtensions(store);
|
|
14538
14653
|
onCreated = onCreatedCallback;
|
|
14539
14654
|
configured = true;
|
|
14540
14655
|
resolve();
|
|
@@ -14576,18 +14691,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14576
14691
|
const fiber = root?.fiber;
|
|
14577
14692
|
if (fiber) {
|
|
14578
14693
|
const state = root?.store.getState();
|
|
14579
|
-
if (state)
|
|
14694
|
+
if (state) {
|
|
14695
|
+
state.internal.active = false;
|
|
14696
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14697
|
+
if (unregisterRoot) {
|
|
14698
|
+
unregisterRoot();
|
|
14699
|
+
state.internal.unregisterRoot = void 0;
|
|
14700
|
+
}
|
|
14701
|
+
}
|
|
14580
14702
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14703
|
+
if (root?.store) detachRootExtensions(root.store);
|
|
14581
14704
|
if (state) {
|
|
14582
14705
|
setTimeout(() => {
|
|
14583
14706
|
try {
|
|
14584
14707
|
const renderer = state.internal.actualRenderer;
|
|
14585
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14586
|
-
if (unregisterRoot) unregisterRoot();
|
|
14587
14708
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14588
14709
|
if (unregisterPrimary) unregisterPrimary();
|
|
14589
14710
|
const canvasTarget = state.internal.canvasTarget;
|
|
14590
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14711
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14591
14712
|
state.events.disconnect?.();
|
|
14592
14713
|
cleanupHelperGroup(root.store);
|
|
14593
14714
|
if (state.isLegacy && renderer) {
|
|
@@ -14728,16 +14849,11 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14728
14849
|
const oldbg = target.background;
|
|
14729
14850
|
const oldenv = target.environment;
|
|
14730
14851
|
const oldSceneProps = {
|
|
14731
|
-
// @ts-ignore
|
|
14732
14852
|
backgroundBlurriness: target.backgroundBlurriness,
|
|
14733
|
-
// @ts-ignore
|
|
14734
14853
|
backgroundIntensity: target.backgroundIntensity,
|
|
14735
|
-
|
|
14736
|
-
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
14737
|
-
// @ts-ignore
|
|
14854
|
+
backgroundRotation: target.backgroundRotation.clone(),
|
|
14738
14855
|
environmentIntensity: target.environmentIntensity,
|
|
14739
|
-
|
|
14740
|
-
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
14856
|
+
environmentRotation: target.environmentRotation.clone()
|
|
14741
14857
|
};
|
|
14742
14858
|
if (background !== "only") target.environment = texture;
|
|
14743
14859
|
if (background) target.background = texture;
|
|
@@ -14962,38 +15078,6 @@ function parseRendererConfig(rendererProp) {
|
|
|
14962
15078
|
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
14963
15079
|
}
|
|
14964
15080
|
|
|
14965
|
-
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
14966
|
-
const registries = /* @__PURE__ */ new WeakMap();
|
|
14967
|
-
function getKindRegistry(store, kind) {
|
|
14968
|
-
let registry = registries.get(store);
|
|
14969
|
-
if (!registry) {
|
|
14970
|
-
registry = {
|
|
14971
|
-
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14972
|
-
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14973
|
-
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14974
|
-
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
14975
|
-
};
|
|
14976
|
-
registries.set(store, registry);
|
|
14977
|
-
}
|
|
14978
|
-
return registry[kind];
|
|
14979
|
-
}
|
|
14980
|
-
function invalidateResource(store, kind, scopeKey) {
|
|
14981
|
-
const registry = getKindRegistry(store, kind);
|
|
14982
|
-
{
|
|
14983
|
-
registry.valid.clear();
|
|
14984
|
-
registry.staged.clear();
|
|
14985
|
-
}
|
|
14986
|
-
}
|
|
14987
|
-
function invalidateAllResources(store) {
|
|
14988
|
-
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
14989
|
-
}
|
|
14990
|
-
|
|
14991
|
-
function clearHmrCaches(store) {
|
|
14992
|
-
const primary = store.getState().primaryStore ?? store;
|
|
14993
|
-
invalidateAllResources(primary);
|
|
14994
|
-
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
14995
|
-
}
|
|
14996
|
-
|
|
14997
15081
|
function CanvasImpl({
|
|
14998
15082
|
ref,
|
|
14999
15083
|
children,
|
|
@@ -15031,9 +15115,9 @@ function CanvasImpl({
|
|
|
15031
15115
|
React__namespace.useMemo(() => extend(THREE), []);
|
|
15032
15116
|
const Bridge = useBridge();
|
|
15033
15117
|
const backgroundProps = React__namespace.useMemo(() => parseBackground(background), [background]);
|
|
15034
|
-
const
|
|
15118
|
+
const [hasInitialSize, setHasInitialSize] = React__namespace.useState(false);
|
|
15035
15119
|
const measureConfig = React__namespace.useMemo(() => {
|
|
15036
|
-
if (!
|
|
15120
|
+
if (!hasInitialSize) {
|
|
15037
15121
|
return {
|
|
15038
15122
|
...resize,
|
|
15039
15123
|
scroll: resize?.scroll ?? true,
|
|
@@ -15045,7 +15129,7 @@ function CanvasImpl({
|
|
|
15045
15129
|
debounce: { scroll: 50, resize: 0 },
|
|
15046
15130
|
...resize
|
|
15047
15131
|
};
|
|
15048
|
-
}, [
|
|
15132
|
+
}, [hasInitialSize, resize]);
|
|
15049
15133
|
const [containerRef, containerRect] = useMeasure__default(measureConfig);
|
|
15050
15134
|
const effectiveSize = React__namespace.useMemo(() => {
|
|
15051
15135
|
let w = width ?? containerRect.width;
|
|
@@ -15061,9 +15145,7 @@ function CanvasImpl({
|
|
|
15061
15145
|
left: containerRect.left
|
|
15062
15146
|
};
|
|
15063
15147
|
}, [width, height, containerRect, forceEven]);
|
|
15064
|
-
if (!
|
|
15065
|
-
hasInitialSizeRef.current = true;
|
|
15066
|
-
}
|
|
15148
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15067
15149
|
const canvasRef = React__namespace.useRef(null);
|
|
15068
15150
|
const divRef = React__namespace.useRef(null);
|
|
15069
15151
|
React__namespace.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15177,6 +15259,7 @@ function CanvasImpl({
|
|
|
15177
15259
|
const canvas = canvasRef.current;
|
|
15178
15260
|
if (canvas) {
|
|
15179
15261
|
return () => {
|
|
15262
|
+
if (canvas.isConnected) return;
|
|
15180
15263
|
unmountComponentAtNode(canvas);
|
|
15181
15264
|
root.current = null;
|
|
15182
15265
|
};
|
|
@@ -15189,7 +15272,7 @@ function CanvasImpl({
|
|
|
15189
15272
|
const handleHMR = () => {
|
|
15190
15273
|
queueMicrotask(() => {
|
|
15191
15274
|
const rootEntry = _roots.get(canvas);
|
|
15192
|
-
if (rootEntry?.store)
|
|
15275
|
+
if (rootEntry?.store) notifyRootExtensionsHmr(rootEntry.store);
|
|
15193
15276
|
});
|
|
15194
15277
|
};
|
|
15195
15278
|
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
@@ -15307,8 +15390,10 @@ exports.prepare = prepare;
|
|
|
15307
15390
|
exports.presetsObj = presetsObj;
|
|
15308
15391
|
exports.reconciler = reconciler;
|
|
15309
15392
|
exports.registerPrimary = registerPrimary;
|
|
15393
|
+
exports.registerRootExtension = registerRootExtension;
|
|
15310
15394
|
exports.removeInteractivity = removeInteractivity;
|
|
15311
15395
|
exports.resolve = resolve;
|
|
15396
|
+
exports.setRenderOverride = setRenderOverride;
|
|
15312
15397
|
exports.swapInteractivity = swapInteractivity;
|
|
15313
15398
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
15314
15399
|
exports.unregisterPrimary = unregisterPrimary;
|