@react-three/fiber 10.0.0-canary.da7a768 → 10.0.0-canary.dc0ec15
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 +994 -898
- package/dist/index.d.cts +331 -155
- package/dist/index.d.mts +331 -155
- package/dist/index.d.ts +331 -183
- package/dist/index.mjs +995 -901
- package/dist/legacy.cjs +1345 -1245
- package/dist/legacy.d.cts +353 -205
- package/dist/legacy.d.mts +353 -205
- package/dist/legacy.d.ts +353 -231
- package/dist/legacy.mjs +1346 -1248
- package/dist/webgpu/index.cjs +908 -713
- package/dist/webgpu/index.d.cts +389 -212
- package/dist/webgpu/index.d.mts +389 -212
- package/dist/webgpu/index.d.ts +389 -240
- package/dist/webgpu/index.mjs +910 -717
- package/package.json +7 -2
package/dist/legacy.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as three from 'three';
|
|
2
|
-
import { WebGLCubeRenderTarget, WebGLRenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType,
|
|
2
|
+
import { WebGLCubeRenderTarget, WebGLRenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType, TextureLoader, Texture as Texture$1, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Vector3, Vector2, Raycaster, OrthographicCamera, PerspectiveCamera, Scene, PCFShadowMap, VSMShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGLRenderer, HalfFloatType, Color } from 'three';
|
|
3
3
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import React__default, { useRef, useMemo, useLayoutEffect, useEffect,
|
|
5
|
+
import React__default, { useContext, useRef, useMemo, useLayoutEffect, useEffect, useImperativeHandle, useCallback, useState } from 'react';
|
|
6
6
|
import useMeasure from 'react-use-measure';
|
|
7
7
|
import { useFiber, useContextBridge, traverseFiber, FiberProvider } from 'its-fine';
|
|
8
8
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
@@ -11,6 +11,7 @@ export { Scheduler, getScheduler } from '@pmndrs/scheduler';
|
|
|
11
11
|
import Tb, { unstable_getCurrentPriorityLevel, unstable_IdlePriority, unstable_LowPriority, unstable_NormalPriority, unstable_UserBlockingPriority, unstable_ImmediatePriority, unstable_scheduleCallback } from 'scheduler';
|
|
12
12
|
import { GroundedSkybox } from 'three/examples/jsm/objects/GroundedSkybox.js';
|
|
13
13
|
import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
|
|
14
|
+
import { HDRCubeTextureLoader } from 'three/examples/jsm/loaders/HDRCubeTextureLoader.js';
|
|
14
15
|
import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js';
|
|
15
16
|
import { UltraHDRLoader } from 'three/examples/jsm/loaders/UltraHDRLoader.js';
|
|
16
17
|
import { GainMapLoader } from '@monogrid/gainmap-js';
|
|
@@ -33,11 +34,11 @@ const R3F_BUILD_WEBGPU = false;
|
|
|
33
34
|
async function loadInspector() {
|
|
34
35
|
throw new Error("Inspector is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
class WebGPURenderer {
|
|
37
38
|
constructor() {
|
|
38
39
|
throw new Error("WebGPURenderer is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
39
40
|
}
|
|
40
|
-
}
|
|
41
|
+
}
|
|
41
42
|
const RenderTarget = null;
|
|
42
43
|
const CubeRenderTarget = null;
|
|
43
44
|
|
|
@@ -297,7 +298,6 @@ function prepare(target, root, type, props) {
|
|
|
297
298
|
}
|
|
298
299
|
function invalidateInstance(instance) {
|
|
299
300
|
if (!instance.parent) return;
|
|
300
|
-
instance.props.onUpdate?.(instance.object);
|
|
301
301
|
const state = instance.root?.getState?.();
|
|
302
302
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
303
303
|
}
|
|
@@ -513,8 +513,10 @@ function hasVisibilityHandlers(handlers) {
|
|
|
513
513
|
}
|
|
514
514
|
|
|
515
515
|
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
516
|
-
function fromRef(ref) {
|
|
517
|
-
|
|
516
|
+
function fromRef(ref, transform) {
|
|
517
|
+
const marker = { [FROM_REF]: ref };
|
|
518
|
+
if (transform) marker.transform = transform;
|
|
519
|
+
return marker;
|
|
518
520
|
}
|
|
519
521
|
function isFromRef(value) {
|
|
520
522
|
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
@@ -528,6 +530,63 @@ function isOnce(value) {
|
|
|
528
530
|
return value !== null && typeof value === "object" && ONCE in value;
|
|
529
531
|
}
|
|
530
532
|
|
|
533
|
+
const shownNotices = /* @__PURE__ */ new Set();
|
|
534
|
+
function notifyDepreciated({ heading, body, link }) {
|
|
535
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
if (shownNotices.has(heading)) return;
|
|
539
|
+
shownNotices.add(heading);
|
|
540
|
+
const caller = getCallerFrame();
|
|
541
|
+
if (caller) {
|
|
542
|
+
console.log();
|
|
543
|
+
}
|
|
544
|
+
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
545
|
+
if (caller) {
|
|
546
|
+
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
547
|
+
}
|
|
548
|
+
if (body || link) {
|
|
549
|
+
let message = "";
|
|
550
|
+
if (body) message += body;
|
|
551
|
+
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
552
|
+
console.warn(`%c${message}`, "font-weight: bold;");
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
function getCallerFrame(depth = 3) {
|
|
556
|
+
const stack = new Error().stack;
|
|
557
|
+
if (!stack) return null;
|
|
558
|
+
const lines = stack.split("\n");
|
|
559
|
+
const frame = lines[depth];
|
|
560
|
+
if (!frame) return null;
|
|
561
|
+
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
562
|
+
if (!match) {
|
|
563
|
+
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
564
|
+
}
|
|
565
|
+
if (!match) return null;
|
|
566
|
+
const [, fn, url, line] = match;
|
|
567
|
+
return {
|
|
568
|
+
functionName: fn ?? "<anonymous>",
|
|
569
|
+
location: formatLocation(url, Number(line))
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function formatLocation(url, line) {
|
|
573
|
+
const clean = url.split("?")[0];
|
|
574
|
+
const file = clean.split("/").pop() ?? clean;
|
|
575
|
+
return `${file}:${line}`;
|
|
576
|
+
}
|
|
577
|
+
function notifyAlpha({ message, link }) {
|
|
578
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (shownNotices.has(message)) return;
|
|
582
|
+
shownNotices.add(message);
|
|
583
|
+
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
584
|
+
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
585
|
+
{
|
|
586
|
+
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
531
590
|
const RESERVED_PROPS = [
|
|
532
591
|
"children",
|
|
533
592
|
"key",
|
|
@@ -537,7 +596,6 @@ const RESERVED_PROPS = [
|
|
|
537
596
|
"dispose",
|
|
538
597
|
"attach",
|
|
539
598
|
"object",
|
|
540
|
-
"onUpdate",
|
|
541
599
|
// Behavior flags
|
|
542
600
|
"dispose"
|
|
543
601
|
];
|
|
@@ -615,11 +673,9 @@ function diffProps(instance, newProps) {
|
|
|
615
673
|
for (const prop in instance.props) {
|
|
616
674
|
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
617
675
|
const { root, key } = resolve(instance.object, prop);
|
|
618
|
-
if (
|
|
676
|
+
if (typeof root?.constructor === "function") {
|
|
619
677
|
const ctor = getMemoizedPrototype(root);
|
|
620
678
|
if (!is.und(ctor)) changedProps[prop] = ctor[key];
|
|
621
|
-
} else {
|
|
622
|
-
changedProps[prop] = 0;
|
|
623
679
|
}
|
|
624
680
|
}
|
|
625
681
|
return changedProps;
|
|
@@ -631,6 +687,13 @@ function applyProps(object, props) {
|
|
|
631
687
|
for (const prop in props) {
|
|
632
688
|
const value = props[prop];
|
|
633
689
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
690
|
+
if (prop === "onUpdate") {
|
|
691
|
+
notifyDepreciated({
|
|
692
|
+
heading: "onUpdate is no longer an R3F prop",
|
|
693
|
+
body: "v10 removed the onUpdate hook: R3F no longer calls it after prop updates. The value is assigned to the object by name. On a Texture that sets three's Texture.onUpdate, which the renderer calls after a GPU upload, not after prop changes. On a node it replaces the Node.onUpdate() method. On other objects it is never called.\n\nUse an effect keyed on the props that change, read the object in useFrame, or use a ref callback.",
|
|
694
|
+
link: "https://docs.pmnd.rs/react-three-fiber/migration/v10#onupdate-removed"
|
|
695
|
+
});
|
|
696
|
+
}
|
|
634
697
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
635
698
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
636
699
|
else delete instance.handlers[prop];
|
|
@@ -736,1059 +799,754 @@ function applyProps(object, props) {
|
|
|
736
799
|
return object;
|
|
737
800
|
}
|
|
738
801
|
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
if (
|
|
745
|
-
|
|
746
|
-
const caller = getCallerFrame();
|
|
747
|
-
if (caller) {
|
|
748
|
-
console.log();
|
|
749
|
-
}
|
|
750
|
-
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
751
|
-
if (caller) {
|
|
752
|
-
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
753
|
-
}
|
|
754
|
-
if (body || link) {
|
|
755
|
-
let message = "";
|
|
756
|
-
if (body) message += body;
|
|
757
|
-
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
758
|
-
console.warn(`%c${message}`, "font-weight: bold;");
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
function getCallerFrame(depth = 3) {
|
|
762
|
-
const stack = new Error().stack;
|
|
763
|
-
if (!stack) return null;
|
|
764
|
-
const lines = stack.split("\n");
|
|
765
|
-
const frame = lines[depth];
|
|
766
|
-
if (!frame) return null;
|
|
767
|
-
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
768
|
-
if (!match) {
|
|
769
|
-
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
770
|
-
}
|
|
771
|
-
if (!match) return null;
|
|
772
|
-
const [, fn, url, line] = match;
|
|
773
|
-
return {
|
|
774
|
-
functionName: fn ?? "<anonymous>",
|
|
775
|
-
location: formatLocation(url, Number(line))
|
|
776
|
-
};
|
|
802
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
803
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
804
|
+
|
|
805
|
+
function useStore() {
|
|
806
|
+
const store = useContext(context);
|
|
807
|
+
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
808
|
+
return store;
|
|
777
809
|
}
|
|
778
|
-
function
|
|
779
|
-
|
|
780
|
-
const file = clean.split("/").pop() ?? clean;
|
|
781
|
-
return `${file}:${line}`;
|
|
810
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
811
|
+
return useStore()(selector, equalityFn);
|
|
782
812
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
if (
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
813
|
+
|
|
814
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
815
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
816
|
+
function getLoader$1(Proto) {
|
|
817
|
+
if (isConstructor$1(Proto)) {
|
|
818
|
+
let loader = memoizedLoaders.get(Proto);
|
|
819
|
+
if (!loader) {
|
|
820
|
+
loader = new Proto();
|
|
821
|
+
memoizedLoaders.set(Proto, loader);
|
|
822
|
+
}
|
|
823
|
+
return loader;
|
|
793
824
|
}
|
|
825
|
+
return Proto;
|
|
794
826
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
827
|
+
function loadingFn(extensions, onProgress) {
|
|
828
|
+
return function(Proto, input) {
|
|
829
|
+
const loader = getLoader$1(Proto);
|
|
830
|
+
if (extensions) extensions(loader);
|
|
831
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
832
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
833
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
834
|
+
return data;
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
return new Promise(
|
|
838
|
+
(res, reject) => loader.load(
|
|
839
|
+
input,
|
|
840
|
+
(data) => {
|
|
841
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
842
|
+
res(data);
|
|
843
|
+
},
|
|
844
|
+
onProgress,
|
|
845
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
846
|
+
)
|
|
847
|
+
);
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
851
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
852
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
853
|
+
const fn = loadingFn(extensions, onProgress);
|
|
854
|
+
const results = cacheKeys.map(
|
|
855
|
+
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
856
|
+
);
|
|
857
|
+
const stableRef = useRef(null);
|
|
858
|
+
const previous = stableRef.current;
|
|
859
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
860
|
+
stableRef.current = stable;
|
|
861
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
801
862
|
}
|
|
863
|
+
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
864
|
+
const inputs = Array.isArray(input) ? input : [input];
|
|
865
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
866
|
+
cacheKeys.forEach(
|
|
867
|
+
(key, index) => preload(() => loadingFn(extensions, onProgress)(loader, inputs[index]), [loader, key])
|
|
868
|
+
);
|
|
869
|
+
};
|
|
870
|
+
useLoader.clear = function(loader, input, cacheKey) {
|
|
871
|
+
const cacheKeys = Array.isArray(cacheKey ?? input) ? cacheKey ?? input : [cacheKey ?? input];
|
|
872
|
+
cacheKeys.forEach((key) => clear([loader, key]));
|
|
873
|
+
};
|
|
874
|
+
useLoader.loader = getLoader$1;
|
|
802
875
|
|
|
803
|
-
|
|
804
|
-
const
|
|
805
|
-
const
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
876
|
+
function useFrame$1(callback, priorityOrOptions) {
|
|
877
|
+
const store = React.useContext(context);
|
|
878
|
+
const isInsideCanvas = store !== null;
|
|
879
|
+
const scheduler = getScheduler();
|
|
880
|
+
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
881
|
+
id: priorityOrOptions.id,
|
|
882
|
+
phase: priorityOrOptions.phase,
|
|
883
|
+
priority: priorityOrOptions.priority,
|
|
884
|
+
fps: priorityOrOptions.fps,
|
|
885
|
+
drop: priorityOrOptions.drop,
|
|
886
|
+
enabled: priorityOrOptions.enabled,
|
|
887
|
+
before: priorityOrOptions.before,
|
|
888
|
+
after: priorityOrOptions.after
|
|
889
|
+
}) : "";
|
|
890
|
+
const options = React.useMemo(() => {
|
|
891
|
+
return typeof priorityOrOptions === "number" ? { priority: priorityOrOptions } : priorityOrOptions ?? {};
|
|
892
|
+
}, [optionsKey]);
|
|
893
|
+
const reactId = React.useId();
|
|
894
|
+
const id = options.id ?? reactId;
|
|
895
|
+
const callbackRef = useMutableCallback(callback);
|
|
896
|
+
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
897
|
+
useIsomorphicLayoutEffect(() => {
|
|
898
|
+
if (!callback) return;
|
|
899
|
+
if (isInsideCanvas) {
|
|
900
|
+
const state = store.getState();
|
|
901
|
+
const rootId = state.internal.rootId;
|
|
902
|
+
if (isLegacyPriority) {
|
|
903
|
+
state.internal.priority++;
|
|
904
|
+
let parentRoot = state.previousRoot;
|
|
905
|
+
while (parentRoot) {
|
|
906
|
+
const parentState = parentRoot.getState();
|
|
907
|
+
if (parentState?.internal) parentState.internal.priority++;
|
|
908
|
+
parentRoot = parentState?.previousRoot;
|
|
909
|
+
}
|
|
910
|
+
notifyDepreciated({
|
|
911
|
+
heading: "useFrame with numeric priority is deprecated",
|
|
912
|
+
body: 'Using useFrame(callback, number) to control render order is deprecated.\n\nFor custom rendering, use: useFrame(callback, { phase: "render" })\nFor execution order within update phase, use: useFrame(callback, { priority: number })',
|
|
913
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
914
|
+
});
|
|
823
915
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
inspector: null,
|
|
852
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
853
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
854
|
-
textureColorSpace: SRGBColorSpace,
|
|
855
|
-
isLegacy: false,
|
|
856
|
-
webGPUSupported: false,
|
|
857
|
-
isNative: false,
|
|
858
|
-
controls: null,
|
|
859
|
-
pointer,
|
|
860
|
-
mouse: pointer,
|
|
861
|
-
frameloop: "always",
|
|
862
|
-
onPointerMissed: void 0,
|
|
863
|
-
onDragOverMissed: void 0,
|
|
864
|
-
onDropMissed: void 0,
|
|
865
|
-
performance: {
|
|
866
|
-
current: 1,
|
|
867
|
-
min: 0.5,
|
|
868
|
-
max: 1,
|
|
869
|
-
debounce: 200,
|
|
870
|
-
regress: () => {
|
|
871
|
-
const state2 = get();
|
|
872
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
873
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
874
|
-
performanceTimeout = setTimeout(
|
|
875
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
876
|
-
state2.performance.debounce
|
|
877
|
-
);
|
|
878
|
-
}
|
|
879
|
-
},
|
|
880
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
881
|
-
viewport: {
|
|
882
|
-
initialDpr: 0,
|
|
883
|
-
dpr: 0,
|
|
884
|
-
width: 0,
|
|
885
|
-
height: 0,
|
|
886
|
-
top: 0,
|
|
887
|
-
left: 0,
|
|
888
|
-
aspect: 0,
|
|
889
|
-
distance: 0,
|
|
890
|
-
factor: 0,
|
|
891
|
-
getCurrentViewport
|
|
892
|
-
},
|
|
893
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
894
|
-
setSize: (width, height, top, left) => {
|
|
895
|
-
const state2 = get();
|
|
896
|
-
if (width === void 0) {
|
|
897
|
-
set({ _sizeImperative: false });
|
|
898
|
-
if (state2._sizeProps) {
|
|
899
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
900
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
901
|
-
const currentSize = state2.size;
|
|
902
|
-
const newSize = {
|
|
903
|
-
width: propW ?? currentSize.width,
|
|
904
|
-
height: propH ?? currentSize.height,
|
|
905
|
-
top: currentSize.top,
|
|
906
|
-
left: currentSize.left
|
|
907
|
-
};
|
|
908
|
-
set((s) => ({
|
|
909
|
-
size: newSize,
|
|
910
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
911
|
-
}));
|
|
912
|
-
getScheduler().invalidate();
|
|
916
|
+
const wrappedCallback = (frameState, delta) => {
|
|
917
|
+
const localState = store.getState();
|
|
918
|
+
const mergedState = {
|
|
919
|
+
...localState,
|
|
920
|
+
time: frameState.time,
|
|
921
|
+
delta: frameState.delta,
|
|
922
|
+
elapsed: frameState.elapsed,
|
|
923
|
+
frame: frameState.frame
|
|
924
|
+
};
|
|
925
|
+
callbackRef.current?.(mergedState, delta);
|
|
926
|
+
};
|
|
927
|
+
const unregister = scheduler.register(wrappedCallback, {
|
|
928
|
+
id,
|
|
929
|
+
rootId,
|
|
930
|
+
...options
|
|
931
|
+
});
|
|
932
|
+
return () => {
|
|
933
|
+
unregister();
|
|
934
|
+
if (isLegacyPriority) {
|
|
935
|
+
const currentState = store.getState();
|
|
936
|
+
if (currentState.internal) {
|
|
937
|
+
currentState.internal.priority--;
|
|
938
|
+
let parentRoot = currentState.previousRoot;
|
|
939
|
+
while (parentRoot) {
|
|
940
|
+
const parentState = parentRoot.getState();
|
|
941
|
+
if (parentState?.internal) parentState.internal.priority--;
|
|
942
|
+
parentRoot = parentState?.previousRoot;
|
|
913
943
|
}
|
|
914
944
|
}
|
|
915
|
-
return;
|
|
916
945
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
946
|
+
};
|
|
947
|
+
} else {
|
|
948
|
+
return scheduler.register(
|
|
949
|
+
(state, delta) => {
|
|
950
|
+
const frameState = state;
|
|
951
|
+
if (!frameState.renderer) return;
|
|
952
|
+
callbackRef.current?.(frameState, delta);
|
|
953
|
+
},
|
|
954
|
+
{ id, ...options }
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
}, [store, scheduler, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
958
|
+
const isPaused = React.useSyncExternalStore(
|
|
959
|
+
// Subscribe function
|
|
960
|
+
React.useCallback(
|
|
961
|
+
(onStoreChange) => {
|
|
962
|
+
return getScheduler().subscribeJobState(id, onStoreChange);
|
|
928
963
|
},
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
964
|
+
[id]
|
|
965
|
+
),
|
|
966
|
+
// getSnapshot function
|
|
967
|
+
React.useCallback(() => getScheduler().isJobPaused(id), [id]),
|
|
968
|
+
// getServerSnapshot function (SSR)
|
|
969
|
+
React.useCallback(() => false, [])
|
|
970
|
+
);
|
|
971
|
+
const controls = React.useMemo(() => {
|
|
972
|
+
const scheduler2 = getScheduler();
|
|
973
|
+
return {
|
|
974
|
+
/** The job's unique ID */
|
|
975
|
+
id,
|
|
976
|
+
/**
|
|
977
|
+
* Access to the global scheduler for frame loop control.
|
|
978
|
+
* Use for controlling the entire frame loop, adding phases, etc.
|
|
979
|
+
*/
|
|
980
|
+
scheduler: scheduler2,
|
|
981
|
+
/**
|
|
982
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
983
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
984
|
+
*/
|
|
985
|
+
get rootId() {
|
|
986
|
+
return getScheduler().getJobRootId(id);
|
|
936
987
|
},
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
internal.subscribers.push({ ref, priority, store });
|
|
980
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
981
|
-
return () => {
|
|
982
|
-
const internal2 = get().internal;
|
|
983
|
-
if (internal2?.subscribers) {
|
|
984
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
985
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
986
|
-
}
|
|
987
|
-
};
|
|
988
|
-
},
|
|
989
|
-
// Renderer Storage (single source of truth)
|
|
990
|
-
actualRenderer: null,
|
|
991
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
992
|
-
scheduler: null
|
|
993
|
-
}
|
|
988
|
+
/**
|
|
989
|
+
* Manually step this job only.
|
|
990
|
+
* Bypasses FPS limiting - always runs.
|
|
991
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
992
|
+
*/
|
|
993
|
+
step: (timestamp) => {
|
|
994
|
+
getScheduler().stepJob(id, timestamp);
|
|
995
|
+
},
|
|
996
|
+
/**
|
|
997
|
+
* Manually step ALL jobs in the scheduler.
|
|
998
|
+
* Useful for frameloop='never' mode.
|
|
999
|
+
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1000
|
+
*/
|
|
1001
|
+
stepAll: (timestamp) => {
|
|
1002
|
+
getScheduler().step(timestamp);
|
|
1003
|
+
},
|
|
1004
|
+
/**
|
|
1005
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1006
|
+
*/
|
|
1007
|
+
invalidate: (frames, stackFrames) => {
|
|
1008
|
+
const scheduler3 = getScheduler();
|
|
1009
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1010
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1011
|
+
},
|
|
1012
|
+
/**
|
|
1013
|
+
* Pause this job (set enabled=false).
|
|
1014
|
+
* Job remains registered but won't run.
|
|
1015
|
+
*/
|
|
1016
|
+
pause: () => {
|
|
1017
|
+
getScheduler().pauseJob(id);
|
|
1018
|
+
},
|
|
1019
|
+
/**
|
|
1020
|
+
* Resume this job (set enabled=true).
|
|
1021
|
+
*/
|
|
1022
|
+
resume: () => {
|
|
1023
|
+
getScheduler().resumeJob(id);
|
|
1024
|
+
},
|
|
1025
|
+
/**
|
|
1026
|
+
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1027
|
+
* No need for forceUpdate() in your components.
|
|
1028
|
+
*/
|
|
1029
|
+
isPaused
|
|
994
1030
|
};
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
set(value) {
|
|
1024
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1025
|
-
},
|
|
1026
|
-
enumerable: true,
|
|
1027
|
-
configurable: true
|
|
1028
|
-
});
|
|
1029
|
-
let oldScene = state.scene;
|
|
1030
|
-
rootStore.subscribe(() => {
|
|
1031
|
-
const currentState = rootStore.getState();
|
|
1032
|
-
const { scene, rootScene, set } = currentState;
|
|
1033
|
-
if (scene !== oldScene) {
|
|
1034
|
-
oldScene = scene;
|
|
1035
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1036
|
-
set({ rootScene: scene });
|
|
1037
|
-
}
|
|
1031
|
+
}, [id, isPaused]);
|
|
1032
|
+
return controls;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1036
|
+
function getUrls(input) {
|
|
1037
|
+
if (typeof input === "string") return [input];
|
|
1038
|
+
if (Array.isArray(input)) return input;
|
|
1039
|
+
return Object.values(input);
|
|
1040
|
+
}
|
|
1041
|
+
function inputSignature(input) {
|
|
1042
|
+
if (typeof input === "string") return input;
|
|
1043
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1044
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1045
|
+
}
|
|
1046
|
+
function allUrlsCached(urls, textureCache) {
|
|
1047
|
+
return urls.every((url) => textureCache.has(url));
|
|
1048
|
+
}
|
|
1049
|
+
function buildFromCache(input, textureCache) {
|
|
1050
|
+
if (typeof input === "string") {
|
|
1051
|
+
return textureCache.get(input);
|
|
1052
|
+
} else if (Array.isArray(input)) {
|
|
1053
|
+
return input.map((url) => textureCache.get(url));
|
|
1054
|
+
} else {
|
|
1055
|
+
const result = {};
|
|
1056
|
+
const objInput = input;
|
|
1057
|
+
for (const key in objInput) {
|
|
1058
|
+
result[key] = textureCache.get(objInput[key]);
|
|
1038
1059
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
+
return result;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
function useTexture(input, optionsOrOnLoad) {
|
|
1064
|
+
const renderer = useThree$1((state) => state.internal.actualRenderer);
|
|
1065
|
+
const store = useStore();
|
|
1066
|
+
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1067
|
+
const { onLoad, cache = true } = options;
|
|
1068
|
+
const onLoadRef = useRef(onLoad);
|
|
1069
|
+
onLoadRef.current = onLoad;
|
|
1070
|
+
const onLoadCalledForRef = useRef(null);
|
|
1071
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
1072
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
1073
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1074
|
+
const cachedResult = useMemo(() => {
|
|
1075
|
+
if (!cache) return null;
|
|
1076
|
+
const textures = store.getState().textures;
|
|
1077
|
+
if (!allUrlsCached(urls, textures)) return null;
|
|
1078
|
+
return buildFromCache(stableInput, textures);
|
|
1079
|
+
}, [cache, urls, stableInput, store]);
|
|
1080
|
+
const loadedTextures = useLoader(
|
|
1081
|
+
TextureLoader,
|
|
1082
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1083
|
+
);
|
|
1084
|
+
const mappedTextures = useMemo(() => {
|
|
1085
|
+
if (cachedResult) return cachedResult;
|
|
1086
|
+
if (IsObject(stableInput)) {
|
|
1087
|
+
const keyed = {};
|
|
1088
|
+
const textureArray = loadedTextures;
|
|
1089
|
+
let i = 0;
|
|
1090
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1091
|
+
return keyed;
|
|
1092
|
+
} else {
|
|
1093
|
+
return loadedTextures;
|
|
1094
|
+
}
|
|
1095
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1096
|
+
useLayoutEffect(() => {
|
|
1097
|
+
if (cachedResult) return;
|
|
1098
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
1099
|
+
onLoadCalledForRef.current = inputKey;
|
|
1100
|
+
onLoadRef.current?.(mappedTextures);
|
|
1101
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
1102
|
+
useEffect(() => {
|
|
1103
|
+
if (cachedResult) return;
|
|
1104
|
+
if ("initTexture" in renderer) {
|
|
1105
|
+
let textureArray = [];
|
|
1106
|
+
if (Array.isArray(loadedTextures)) {
|
|
1107
|
+
textureArray = loadedTextures;
|
|
1108
|
+
} else if (loadedTextures instanceof Texture$1) {
|
|
1109
|
+
textureArray = [loadedTextures];
|
|
1110
|
+
} else if (IsObject(loadedTextures)) {
|
|
1111
|
+
textureArray = Object.values(loadedTextures);
|
|
1112
|
+
}
|
|
1113
|
+
textureArray.forEach((texture) => {
|
|
1114
|
+
if (texture instanceof Texture$1) {
|
|
1115
|
+
renderer.initTexture(texture);
|
|
1060
1116
|
}
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
}, [renderer, loadedTextures, cachedResult]);
|
|
1120
|
+
useEffect(() => {
|
|
1121
|
+
if (!cache) return;
|
|
1122
|
+
const urlTextureMap = [];
|
|
1123
|
+
if (typeof stableInput === "string") {
|
|
1124
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1125
|
+
} else if (Array.isArray(stableInput)) {
|
|
1126
|
+
const textureArray = mappedTextures;
|
|
1127
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1128
|
+
} else if (IsObject(stableInput)) {
|
|
1129
|
+
const textureRecord = mappedTextures;
|
|
1130
|
+
for (const key in stableInput) {
|
|
1131
|
+
const url = stableInput[key];
|
|
1132
|
+
urlTextureMap.push([url, textureRecord[key]]);
|
|
1061
1133
|
}
|
|
1062
1134
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1135
|
+
store.setState((state) => {
|
|
1136
|
+
const refs = new Map(state._textureRefs);
|
|
1137
|
+
let textures = state.textures;
|
|
1138
|
+
let added = false;
|
|
1139
|
+
for (const [url, texture] of urlTextureMap) {
|
|
1140
|
+
if (!textures.has(url)) {
|
|
1141
|
+
if (!added) {
|
|
1142
|
+
textures = new Map(textures);
|
|
1143
|
+
added = true;
|
|
1144
|
+
}
|
|
1145
|
+
textures.set(url, texture);
|
|
1146
|
+
}
|
|
1147
|
+
refs.set(url, (refs.get(url) ?? 0) + 1);
|
|
1068
1148
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1149
|
+
return added ? { textures, _textureRefs: refs } : { _textureRefs: refs };
|
|
1150
|
+
});
|
|
1151
|
+
return () => store.setState((state) => {
|
|
1152
|
+
const refs = new Map(state._textureRefs);
|
|
1153
|
+
for (const [url] of urlTextureMap) {
|
|
1154
|
+
const next = (refs.get(url) ?? 0) - 1;
|
|
1155
|
+
if (next <= 0) refs.delete(url);
|
|
1156
|
+
else refs.set(url, next);
|
|
1073
1157
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
return
|
|
1158
|
+
return { _textureRefs: refs };
|
|
1159
|
+
});
|
|
1160
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1161
|
+
return mappedTextures;
|
|
1162
|
+
}
|
|
1163
|
+
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
1164
|
+
useTexture.clear = (input) => useLoader.clear(TextureLoader, input);
|
|
1165
|
+
const Texture = ({
|
|
1166
|
+
children,
|
|
1167
|
+
input,
|
|
1168
|
+
onLoad,
|
|
1169
|
+
cache
|
|
1170
|
+
}) => {
|
|
1171
|
+
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1172
|
+
const ret = useTexture(input, options);
|
|
1173
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children?.(ret) });
|
|
1078
1174
|
};
|
|
1079
1175
|
|
|
1080
|
-
|
|
1081
|
-
const
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1176
|
+
function useTextures(selector) {
|
|
1177
|
+
const store = useStore();
|
|
1178
|
+
const registry = useMemo(() => {
|
|
1179
|
+
const getState = store.getState;
|
|
1180
|
+
const setState = store.setState;
|
|
1181
|
+
const getOne = (key) => getState().textures.get(key);
|
|
1182
|
+
return {
|
|
1183
|
+
get all() {
|
|
1184
|
+
return getState().textures;
|
|
1185
|
+
},
|
|
1186
|
+
get(input) {
|
|
1187
|
+
if (typeof input === "string") return getOne(input);
|
|
1188
|
+
if (Array.isArray(input)) return input.map(getOne);
|
|
1189
|
+
const out = {};
|
|
1190
|
+
for (const name in input) out[name] = getOne(input[name]);
|
|
1191
|
+
return out;
|
|
1192
|
+
},
|
|
1193
|
+
has: (key) => getState().textures.has(key),
|
|
1194
|
+
add(keyOrRecord, texture) {
|
|
1195
|
+
setState((state) => {
|
|
1196
|
+
const textures = new Map(state.textures);
|
|
1197
|
+
if (typeof keyOrRecord === "string") {
|
|
1198
|
+
textures.set(keyOrRecord, texture);
|
|
1199
|
+
} else {
|
|
1200
|
+
for (const key in keyOrRecord) textures.set(key, keyOrRecord[key]);
|
|
1201
|
+
}
|
|
1202
|
+
return { textures };
|
|
1203
|
+
});
|
|
1204
|
+
},
|
|
1205
|
+
dispose(key, options) {
|
|
1206
|
+
const state = getState();
|
|
1207
|
+
const refs = state._textureRefs.get(key) ?? 0;
|
|
1208
|
+
if (refs > 0 && !options?.force) {
|
|
1209
|
+
console.warn(
|
|
1210
|
+
`[useTextures] "${key}" still has ${refs} active reference(s); skipping dispose. Pass { force: true } to override.`
|
|
1211
|
+
);
|
|
1212
|
+
return false;
|
|
1213
|
+
}
|
|
1214
|
+
state.textures.get(key)?.dispose();
|
|
1215
|
+
setState((s) => {
|
|
1216
|
+
const textures = new Map(s.textures);
|
|
1217
|
+
textures.delete(key);
|
|
1218
|
+
const nextRefs = new Map(s._textureRefs);
|
|
1219
|
+
nextRefs.delete(key);
|
|
1220
|
+
return { textures, _textureRefs: nextRefs };
|
|
1221
|
+
});
|
|
1222
|
+
return true;
|
|
1223
|
+
},
|
|
1224
|
+
disposeAll() {
|
|
1225
|
+
for (const texture of getState().textures.values()) texture.dispose();
|
|
1226
|
+
setState({ textures: /* @__PURE__ */ new Map(), _textureRefs: /* @__PURE__ */ new Map() });
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
}, [store]);
|
|
1230
|
+
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
1231
|
+
const selected = useThree$1(subscribe);
|
|
1232
|
+
return selector ? selected : registry;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
1236
|
+
const isLegacy = useThree$1((s) => s.isLegacy);
|
|
1237
|
+
const size = useThree$1((s) => s.size);
|
|
1238
|
+
let width;
|
|
1239
|
+
let height;
|
|
1240
|
+
let opts;
|
|
1241
|
+
if (typeof widthOrOptions === "object") {
|
|
1242
|
+
opts = widthOrOptions;
|
|
1243
|
+
} else if (typeof widthOrOptions === "number") {
|
|
1244
|
+
width = widthOrOptions;
|
|
1245
|
+
if (typeof heightOrOptions === "object") {
|
|
1246
|
+
height = widthOrOptions;
|
|
1247
|
+
opts = heightOrOptions;
|
|
1248
|
+
} else if (typeof heightOrOptions === "number") {
|
|
1249
|
+
height = heightOrOptions;
|
|
1250
|
+
opts = options;
|
|
1251
|
+
} else {
|
|
1252
|
+
height = widthOrOptions;
|
|
1088
1253
|
}
|
|
1089
|
-
return loader;
|
|
1090
1254
|
}
|
|
1091
|
-
return
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
if (extensions) extensions(loader);
|
|
1097
|
-
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
1098
|
-
return loader.loadAsync(input, onProgress).then((data) => {
|
|
1099
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1100
|
-
return data;
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
return new Promise(
|
|
1104
|
-
(res, reject) => loader.load(
|
|
1105
|
-
input,
|
|
1106
|
-
(data) => {
|
|
1107
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1108
|
-
res(data);
|
|
1109
|
-
},
|
|
1110
|
-
onProgress,
|
|
1111
|
-
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
1112
|
-
)
|
|
1113
|
-
);
|
|
1114
|
-
};
|
|
1255
|
+
return useMemo(() => {
|
|
1256
|
+
const w = width ?? size.width;
|
|
1257
|
+
const h = height ?? size.height;
|
|
1258
|
+
return new WebGLRenderTarget(w, h, opts);
|
|
1259
|
+
}, [width, height, size.width, size.height, opts, isLegacy]);
|
|
1115
1260
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1261
|
+
|
|
1262
|
+
const presetsObj = {
|
|
1263
|
+
apartment: "lebombo_1k.hdr",
|
|
1264
|
+
city: "potsdamer_platz_1k.hdr",
|
|
1265
|
+
dawn: "kiara_1_dawn_1k.hdr",
|
|
1266
|
+
forest: "forest_slope_1k.hdr",
|
|
1267
|
+
lobby: "st_fagans_interior_1k.hdr",
|
|
1268
|
+
night: "dikhololo_night_1k.hdr",
|
|
1269
|
+
park: "rooitou_park_1k.hdr",
|
|
1270
|
+
studio: "studio_small_03_1k.hdr",
|
|
1271
|
+
sunset: "venice_sunset_1k.hdr",
|
|
1272
|
+
warehouse: "empty_warehouse_01_1k.hdr"
|
|
1273
|
+
};
|
|
1274
|
+
|
|
1275
|
+
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
1276
|
+
const isArray = (arr) => Array.isArray(arr);
|
|
1277
|
+
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
1278
|
+
function useEnvironment({
|
|
1279
|
+
files = defaultFiles,
|
|
1280
|
+
path = "",
|
|
1281
|
+
preset = void 0,
|
|
1282
|
+
colorSpace = void 0,
|
|
1283
|
+
extensions
|
|
1284
|
+
} = {}) {
|
|
1285
|
+
if (preset) {
|
|
1286
|
+
validatePreset(preset);
|
|
1287
|
+
files = presetsObj[preset];
|
|
1288
|
+
path = CUBEMAP_ROOT;
|
|
1289
|
+
}
|
|
1290
|
+
const multiFile = isArray(files);
|
|
1291
|
+
const { extension, isCubemap } = getExtension(files);
|
|
1292
|
+
const loader = getLoader(extension);
|
|
1293
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1294
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
1295
|
+
useLayoutEffect(() => {
|
|
1296
|
+
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
1297
|
+
function clearGainmapTexture() {
|
|
1298
|
+
useLoader.clear(loader, multiFile ? [files] : files);
|
|
1299
|
+
}
|
|
1300
|
+
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
1301
|
+
}, [extension, files, loader, multiFile, renderer.domElement]);
|
|
1302
|
+
const loaderResult = useLoader(
|
|
1303
|
+
loader,
|
|
1304
|
+
multiFile ? [files] : files,
|
|
1305
|
+
(loader2) => {
|
|
1306
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
1307
|
+
loader2.setRenderer?.(renderer);
|
|
1308
|
+
}
|
|
1309
|
+
loader2.setPath?.(path);
|
|
1310
|
+
if (extensions) extensions(loader2);
|
|
1311
|
+
}
|
|
1122
1312
|
);
|
|
1123
|
-
|
|
1313
|
+
let texture = multiFile ? (
|
|
1314
|
+
// @ts-ignore
|
|
1315
|
+
loaderResult[0]
|
|
1316
|
+
) : loaderResult;
|
|
1317
|
+
if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
|
|
1318
|
+
texture = texture.renderTarget?.texture;
|
|
1319
|
+
}
|
|
1320
|
+
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
1321
|
+
texture.colorSpace = colorSpace ?? (isCubemap && extension !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
1322
|
+
return texture;
|
|
1124
1323
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
);
|
|
1324
|
+
const preloadDefaultOptions = {
|
|
1325
|
+
files: defaultFiles,
|
|
1326
|
+
path: "",
|
|
1327
|
+
preset: void 0,
|
|
1328
|
+
extensions: void 0
|
|
1131
1329
|
};
|
|
1132
|
-
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1330
|
+
useEnvironment.preload = (preloadOptions) => {
|
|
1331
|
+
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
1332
|
+
let { files, path = "" } = options;
|
|
1333
|
+
const { preset, extensions } = options;
|
|
1334
|
+
if (preset) {
|
|
1335
|
+
validatePreset(preset);
|
|
1336
|
+
files = presetsObj[preset];
|
|
1337
|
+
path = CUBEMAP_ROOT;
|
|
1338
|
+
}
|
|
1339
|
+
const { extension } = getExtension(files);
|
|
1340
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
1341
|
+
throw new Error("useEnvironment: Preloading gainmaps is not supported");
|
|
1342
|
+
}
|
|
1343
|
+
const loader = getLoader(extension);
|
|
1344
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1345
|
+
useLoader.preload(loader, isArray(files) ? [files] : files, (loader2) => {
|
|
1346
|
+
loader2.setPath?.(path);
|
|
1347
|
+
if (extensions) extensions(loader2);
|
|
1348
|
+
});
|
|
1135
1349
|
};
|
|
1136
|
-
|
|
1350
|
+
const clearDefaultOptins = {
|
|
1351
|
+
files: defaultFiles,
|
|
1352
|
+
preset: void 0
|
|
1353
|
+
};
|
|
1354
|
+
useEnvironment.clear = (clearOptions) => {
|
|
1355
|
+
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
1356
|
+
let { files } = options;
|
|
1357
|
+
const { preset } = options;
|
|
1358
|
+
if (preset) {
|
|
1359
|
+
validatePreset(preset);
|
|
1360
|
+
files = presetsObj[preset];
|
|
1361
|
+
}
|
|
1362
|
+
const { extension } = getExtension(files);
|
|
1363
|
+
const loader = getLoader(extension);
|
|
1364
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1365
|
+
useLoader.clear(loader, isArray(files) ? [files] : files);
|
|
1366
|
+
};
|
|
1367
|
+
function validatePreset(preset) {
|
|
1368
|
+
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
1369
|
+
}
|
|
1370
|
+
function getExtension(files) {
|
|
1371
|
+
const isCubemap = isArray(files) && files.length === 6;
|
|
1372
|
+
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
1373
|
+
const firstEntry = isArray(files) ? files[0] : files;
|
|
1374
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1375
|
+
const extension = isCubemap ? firstExtension === "hdr" ? "hdr-cube" : "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstExtension;
|
|
1376
|
+
return { extension, isCubemap, isGainmap };
|
|
1377
|
+
}
|
|
1378
|
+
function getLoader(extension) {
|
|
1379
|
+
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr-cube" ? HDRCubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
1380
|
+
return loader;
|
|
1381
|
+
}
|
|
1137
1382
|
|
|
1138
|
-
function
|
|
1139
|
-
const
|
|
1140
|
-
|
|
1383
|
+
function useInstanceHandle(ref) {
|
|
1384
|
+
const instance = useRef(null);
|
|
1385
|
+
useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
1386
|
+
return instance;
|
|
1387
|
+
}
|
|
1388
|
+
function useGraph(object) {
|
|
1389
|
+
return useMemo(() => buildGraph(object), [object]);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
const t = 1, o = 8, r = 32, e = 2, i$1 = 268435456;
|
|
1393
|
+
|
|
1394
|
+
let effectId = 0;
|
|
1395
|
+
function addEffect(callback) {
|
|
1396
|
+
notifyDepreciated({
|
|
1397
|
+
heading: "addEffect is deprecated",
|
|
1398
|
+
body: 'Use useFrame(callback, { phase: "start" }) instead.\naddEffect will be removed in a future version.',
|
|
1399
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1400
|
+
});
|
|
1401
|
+
const id = `legacy_effect_${effectId++}`;
|
|
1402
|
+
return getScheduler().registerGlobal("before", id, callback);
|
|
1403
|
+
}
|
|
1404
|
+
function addAfterEffect(callback) {
|
|
1405
|
+
notifyDepreciated({
|
|
1406
|
+
heading: "addAfterEffect is deprecated",
|
|
1407
|
+
body: 'Use useFrame(callback, { phase: "finish" }) instead.\naddAfterEffect will be removed in a future version.',
|
|
1408
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1409
|
+
});
|
|
1410
|
+
const id = `legacy_afterEffect_${effectId++}`;
|
|
1411
|
+
return getScheduler().registerGlobal("after", id, callback);
|
|
1412
|
+
}
|
|
1413
|
+
function addTail(callback) {
|
|
1414
|
+
notifyDepreciated({
|
|
1415
|
+
heading: "addTail is deprecated",
|
|
1416
|
+
body: "Use scheduler.onIdle(callback) instead.\naddTail will be removed in a future version.",
|
|
1417
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1418
|
+
});
|
|
1419
|
+
return getScheduler().onIdle(callback);
|
|
1420
|
+
}
|
|
1421
|
+
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1422
|
+
const rootId = state?.internal?.rootId;
|
|
1141
1423
|
const scheduler = getScheduler();
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1424
|
+
if (rootId) scheduler.invalidateRoot(rootId, frames, stackFrames);
|
|
1425
|
+
else scheduler.invalidate(frames, stackFrames);
|
|
1426
|
+
}
|
|
1427
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1428
|
+
const rootId = state?.internal?.rootId;
|
|
1429
|
+
const scheduler = getScheduler();
|
|
1430
|
+
if (rootId) scheduler.stepRoot(rootId, timestamp);
|
|
1431
|
+
else scheduler.step(timestamp);
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
const version = "10.0.0-alpha.5";
|
|
1435
|
+
const packageData = {
|
|
1436
|
+
version: version};
|
|
1437
|
+
|
|
1438
|
+
function Xb(Tt) {
|
|
1439
|
+
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
1440
|
+
}
|
|
1441
|
+
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
1442
|
+
function Kb() {
|
|
1443
|
+
return _b || (_b = 1, (function(Tt) {
|
|
1444
|
+
Tt.exports = function(m) {
|
|
1445
|
+
function Yn(t, r, a, l) {
|
|
1446
|
+
return new uc(t, r, a, l);
|
|
1447
|
+
}
|
|
1448
|
+
function _d() {
|
|
1449
|
+
}
|
|
1450
|
+
function F(t) {
|
|
1451
|
+
var r = "https://react.dev/errors/" + t;
|
|
1452
|
+
if (1 < arguments.length) {
|
|
1453
|
+
r += "?args[]=" + encodeURIComponent(arguments[1]);
|
|
1454
|
+
for (var a = 2; a < arguments.length; a++) r += "&args[]=" + encodeURIComponent(arguments[a]);
|
|
1171
1455
|
}
|
|
1172
|
-
|
|
1173
|
-
heading: "useFrame with numeric priority is deprecated",
|
|
1174
|
-
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 })',
|
|
1175
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1176
|
-
});
|
|
1456
|
+
return "Minified React error #" + t + "; visit " + r + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";
|
|
1177
1457
|
}
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
};
|
|
1187
|
-
callbackRef.current?.(mergedState, delta);
|
|
1188
|
-
};
|
|
1189
|
-
const unregister = scheduler.register(wrappedCallback, {
|
|
1190
|
-
id,
|
|
1191
|
-
rootId,
|
|
1192
|
-
...options
|
|
1193
|
-
});
|
|
1194
|
-
return () => {
|
|
1195
|
-
unregister();
|
|
1196
|
-
if (isLegacyPriority) {
|
|
1197
|
-
const currentState = store.getState();
|
|
1198
|
-
if (currentState.internal) {
|
|
1199
|
-
currentState.internal.priority--;
|
|
1200
|
-
let parentRoot = currentState.previousRoot;
|
|
1201
|
-
while (parentRoot) {
|
|
1202
|
-
const parentState = parentRoot.getState();
|
|
1203
|
-
if (parentState?.internal) parentState.internal.priority--;
|
|
1204
|
-
parentRoot = parentState?.previousRoot;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1458
|
+
function Rd(t) {
|
|
1459
|
+
var r = t, a = t;
|
|
1460
|
+
if (t.alternate) for (; r.return; ) r = r.return;
|
|
1461
|
+
else {
|
|
1462
|
+
t = r;
|
|
1463
|
+
do
|
|
1464
|
+
r = t, (r.flags & 4098) !== 0 && (a = r.return), t = r.return;
|
|
1465
|
+
while (t);
|
|
1207
1466
|
}
|
|
1208
|
-
|
|
1209
|
-
} else {
|
|
1210
|
-
return scheduler.register(
|
|
1211
|
-
(state, delta) => {
|
|
1212
|
-
const frameState = state;
|
|
1213
|
-
if (!frameState.renderer) return;
|
|
1214
|
-
callbackRef.current?.(frameState, delta);
|
|
1215
|
-
},
|
|
1216
|
-
{ id, ...options }
|
|
1217
|
-
);
|
|
1218
|
-
}
|
|
1219
|
-
}, [store, scheduler, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
1220
|
-
const isPaused = React.useSyncExternalStore(
|
|
1221
|
-
// Subscribe function
|
|
1222
|
-
React.useCallback(
|
|
1223
|
-
(onStoreChange) => {
|
|
1224
|
-
return getScheduler().subscribeJobState(id, onStoreChange);
|
|
1225
|
-
},
|
|
1226
|
-
[id]
|
|
1227
|
-
),
|
|
1228
|
-
// getSnapshot function
|
|
1229
|
-
React.useCallback(() => getScheduler().isJobPaused(id), [id]),
|
|
1230
|
-
// getServerSnapshot function (SSR)
|
|
1231
|
-
React.useCallback(() => false, [])
|
|
1232
|
-
);
|
|
1233
|
-
const controls = React.useMemo(() => {
|
|
1234
|
-
const scheduler2 = getScheduler();
|
|
1235
|
-
return {
|
|
1236
|
-
/** The job's unique ID */
|
|
1237
|
-
id,
|
|
1238
|
-
/**
|
|
1239
|
-
* Access to the global scheduler for frame loop control.
|
|
1240
|
-
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1241
|
-
*/
|
|
1242
|
-
scheduler: scheduler2,
|
|
1243
|
-
/**
|
|
1244
|
-
* Manually step this job only.
|
|
1245
|
-
* Bypasses FPS limiting - always runs.
|
|
1246
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1247
|
-
*/
|
|
1248
|
-
step: (timestamp) => {
|
|
1249
|
-
getScheduler().stepJob(id, timestamp);
|
|
1250
|
-
},
|
|
1251
|
-
/**
|
|
1252
|
-
* Manually step ALL jobs in the scheduler.
|
|
1253
|
-
* Useful for frameloop='never' mode.
|
|
1254
|
-
* @param timestamp Optional timestamp (defaults to performance.now())
|
|
1255
|
-
*/
|
|
1256
|
-
stepAll: (timestamp) => {
|
|
1257
|
-
getScheduler().step(timestamp);
|
|
1258
|
-
},
|
|
1259
|
-
/**
|
|
1260
|
-
* Pause this job (set enabled=false).
|
|
1261
|
-
* Job remains registered but won't run.
|
|
1262
|
-
*/
|
|
1263
|
-
pause: () => {
|
|
1264
|
-
getScheduler().pauseJob(id);
|
|
1265
|
-
},
|
|
1266
|
-
/**
|
|
1267
|
-
* Resume this job (set enabled=true).
|
|
1268
|
-
*/
|
|
1269
|
-
resume: () => {
|
|
1270
|
-
getScheduler().resumeJob(id);
|
|
1271
|
-
},
|
|
1272
|
-
/**
|
|
1273
|
-
* Reactive paused state - automatically updates when pause/resume is called.
|
|
1274
|
-
* No need for forceUpdate() in your components.
|
|
1275
|
-
*/
|
|
1276
|
-
isPaused
|
|
1277
|
-
};
|
|
1278
|
-
}, [id, isPaused]);
|
|
1279
|
-
return controls;
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
const IsObject = (url) => url === Object(url) && !Array.isArray(url) && typeof url !== "function";
|
|
1283
|
-
function getUrls(input) {
|
|
1284
|
-
if (typeof input === "string") return [input];
|
|
1285
|
-
if (Array.isArray(input)) return input;
|
|
1286
|
-
return Object.values(input);
|
|
1287
|
-
}
|
|
1288
|
-
function allUrlsCached(urls, textureCache) {
|
|
1289
|
-
return urls.every((url) => textureCache.has(url));
|
|
1290
|
-
}
|
|
1291
|
-
function buildFromCache(input, textureCache) {
|
|
1292
|
-
if (typeof input === "string") {
|
|
1293
|
-
return textureCache.get(input);
|
|
1294
|
-
} else if (Array.isArray(input)) {
|
|
1295
|
-
return input.map((url) => textureCache.get(url));
|
|
1296
|
-
} else {
|
|
1297
|
-
const result = {};
|
|
1298
|
-
const objInput = input;
|
|
1299
|
-
for (const key in objInput) {
|
|
1300
|
-
result[key] = textureCache.get(objInput[key]);
|
|
1301
|
-
}
|
|
1302
|
-
return result;
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
function useTexture(input, optionsOrOnLoad) {
|
|
1306
|
-
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1307
|
-
const store = useStore();
|
|
1308
|
-
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1309
|
-
const { onLoad, cache = true } = options;
|
|
1310
|
-
const onLoadRef = useRef(onLoad);
|
|
1311
|
-
onLoadRef.current = onLoad;
|
|
1312
|
-
const onLoadCalledForRef = useRef(null);
|
|
1313
|
-
const urls = useMemo(() => getUrls(input), [input]);
|
|
1314
|
-
const cachedResult = useMemo(() => {
|
|
1315
|
-
if (!cache) return null;
|
|
1316
|
-
const textures = store.getState().textures;
|
|
1317
|
-
if (!allUrlsCached(urls, textures)) return null;
|
|
1318
|
-
return buildFromCache(input, textures);
|
|
1319
|
-
}, [cache, urls, input, store]);
|
|
1320
|
-
const loadedTextures = useLoader(
|
|
1321
|
-
TextureLoader,
|
|
1322
|
-
IsObject(input) ? Object.values(input) : input
|
|
1323
|
-
);
|
|
1324
|
-
const inputKey = urls.join("\0");
|
|
1325
|
-
useLayoutEffect(() => {
|
|
1326
|
-
if (cachedResult) return;
|
|
1327
|
-
if (onLoadCalledForRef.current === inputKey) return;
|
|
1328
|
-
onLoadCalledForRef.current = inputKey;
|
|
1329
|
-
onLoadRef.current?.(loadedTextures);
|
|
1330
|
-
}, [cachedResult, loadedTextures, inputKey]);
|
|
1331
|
-
useEffect(() => {
|
|
1332
|
-
if (cachedResult) return;
|
|
1333
|
-
if ("initTexture" in renderer) {
|
|
1334
|
-
let textureArray = [];
|
|
1335
|
-
if (Array.isArray(loadedTextures)) {
|
|
1336
|
-
textureArray = loadedTextures;
|
|
1337
|
-
} else if (loadedTextures instanceof Texture$1) {
|
|
1338
|
-
textureArray = [loadedTextures];
|
|
1339
|
-
} else if (IsObject(loadedTextures)) {
|
|
1340
|
-
textureArray = Object.values(loadedTextures);
|
|
1467
|
+
return r.tag === 3 ? a : null;
|
|
1341
1468
|
}
|
|
1342
|
-
|
|
1343
|
-
if (
|
|
1344
|
-
renderer.initTexture(texture);
|
|
1345
|
-
}
|
|
1346
|
-
});
|
|
1347
|
-
}
|
|
1348
|
-
}, [renderer, loadedTextures, cachedResult]);
|
|
1349
|
-
const mappedTextures = useMemo(() => {
|
|
1350
|
-
if (cachedResult) return cachedResult;
|
|
1351
|
-
if (IsObject(input)) {
|
|
1352
|
-
const keyed = {};
|
|
1353
|
-
const textureArray = loadedTextures;
|
|
1354
|
-
let i = 0;
|
|
1355
|
-
for (const key in input) keyed[key] = textureArray[i++];
|
|
1356
|
-
return keyed;
|
|
1357
|
-
} else {
|
|
1358
|
-
return loadedTextures;
|
|
1359
|
-
}
|
|
1360
|
-
}, [input, loadedTextures, cachedResult]);
|
|
1361
|
-
useEffect(() => {
|
|
1362
|
-
if (!cache) return;
|
|
1363
|
-
const urlTextureMap = [];
|
|
1364
|
-
if (typeof input === "string") {
|
|
1365
|
-
urlTextureMap.push([input, mappedTextures]);
|
|
1366
|
-
} else if (Array.isArray(input)) {
|
|
1367
|
-
const textureArray = mappedTextures;
|
|
1368
|
-
input.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1369
|
-
} else if (IsObject(input)) {
|
|
1370
|
-
const textureRecord = mappedTextures;
|
|
1371
|
-
for (const key in input) {
|
|
1372
|
-
const url = input[key];
|
|
1373
|
-
urlTextureMap.push([url, textureRecord[key]]);
|
|
1469
|
+
function du(t) {
|
|
1470
|
+
if (Rd(t) !== t) throw Error(F(188));
|
|
1374
1471
|
}
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1472
|
+
function fu(t) {
|
|
1473
|
+
var r = t.alternate;
|
|
1474
|
+
if (!r) {
|
|
1475
|
+
if (r = Rd(t), r === null) throw Error(F(188));
|
|
1476
|
+
return r !== t ? null : t;
|
|
1477
|
+
}
|
|
1478
|
+
for (var a = t, l = r; ; ) {
|
|
1479
|
+
var c = a.return;
|
|
1480
|
+
if (c === null) break;
|
|
1481
|
+
var d = c.alternate;
|
|
1482
|
+
if (d === null) {
|
|
1483
|
+
if (l = c.return, l !== null) {
|
|
1484
|
+
a = l;
|
|
1485
|
+
continue;
|
|
1486
|
+
}
|
|
1487
|
+
break;
|
|
1385
1488
|
}
|
|
1386
|
-
|
|
1489
|
+
if (c.child === d.child) {
|
|
1490
|
+
for (d = c.child; d; ) {
|
|
1491
|
+
if (d === a) return du(c), t;
|
|
1492
|
+
if (d === l) return du(c), r;
|
|
1493
|
+
d = d.sibling;
|
|
1494
|
+
}
|
|
1495
|
+
throw Error(F(188));
|
|
1496
|
+
}
|
|
1497
|
+
if (a.return !== l.return) a = c, l = d;
|
|
1498
|
+
else {
|
|
1499
|
+
for (var h = false, y = c.child; y; ) {
|
|
1500
|
+
if (y === a) {
|
|
1501
|
+
h = true, a = c, l = d;
|
|
1502
|
+
break;
|
|
1503
|
+
}
|
|
1504
|
+
if (y === l) {
|
|
1505
|
+
h = true, l = c, a = d;
|
|
1506
|
+
break;
|
|
1507
|
+
}
|
|
1508
|
+
y = y.sibling;
|
|
1509
|
+
}
|
|
1510
|
+
if (!h) {
|
|
1511
|
+
for (y = d.child; y; ) {
|
|
1512
|
+
if (y === a) {
|
|
1513
|
+
h = true, a = d, l = c;
|
|
1514
|
+
break;
|
|
1515
|
+
}
|
|
1516
|
+
if (y === l) {
|
|
1517
|
+
h = true, l = d, a = c;
|
|
1518
|
+
break;
|
|
1519
|
+
}
|
|
1520
|
+
y = y.sibling;
|
|
1521
|
+
}
|
|
1522
|
+
if (!h) throw Error(F(189));
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
if (a.alternate !== l) throw Error(F(190));
|
|
1387
1526
|
}
|
|
1388
|
-
|
|
1527
|
+
if (a.tag !== 3) throw Error(F(188));
|
|
1528
|
+
return a.stateNode.current === a ? t : r;
|
|
1389
1529
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1530
|
+
function pu(t) {
|
|
1531
|
+
var r = t.tag;
|
|
1532
|
+
if (r === 5 || r === 26 || r === 27 || r === 6) return t;
|
|
1533
|
+
for (t = t.child; t !== null; ) {
|
|
1534
|
+
if (r = pu(t), r !== null) return r;
|
|
1535
|
+
t = t.sibling;
|
|
1536
|
+
}
|
|
1537
|
+
return null;
|
|
1398
1538
|
}
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
useTexture.clear = (input) => useLoader.clear(TextureLoader, input);
|
|
1406
|
-
const Texture = ({
|
|
1407
|
-
children,
|
|
1408
|
-
input,
|
|
1409
|
-
onLoad,
|
|
1410
|
-
cache
|
|
1411
|
-
}) => {
|
|
1412
|
-
const options = typeof onLoad === "function" ? { onLoad, cache } : { ...onLoad, cache };
|
|
1413
|
-
const ret = useTexture(input, options);
|
|
1414
|
-
return /* @__PURE__ */ jsx(Fragment, { children: children?.(ret) });
|
|
1415
|
-
};
|
|
1416
|
-
|
|
1417
|
-
function useTextures(selector) {
|
|
1418
|
-
const store = useStore();
|
|
1419
|
-
const registry = useMemo(() => {
|
|
1420
|
-
const getState = store.getState;
|
|
1421
|
-
const setState = store.setState;
|
|
1422
|
-
const getOne = (key) => getState().textures.get(key);
|
|
1423
|
-
return {
|
|
1424
|
-
get all() {
|
|
1425
|
-
return getState().textures;
|
|
1426
|
-
},
|
|
1427
|
-
get(input) {
|
|
1428
|
-
if (typeof input === "string") return getOne(input);
|
|
1429
|
-
if (Array.isArray(input)) return input.map(getOne);
|
|
1430
|
-
const out = {};
|
|
1431
|
-
for (const name in input) out[name] = getOne(input[name]);
|
|
1432
|
-
return out;
|
|
1433
|
-
},
|
|
1434
|
-
has: (key) => getState().textures.has(key),
|
|
1435
|
-
add(keyOrRecord, texture) {
|
|
1436
|
-
setState((state) => {
|
|
1437
|
-
const textures = new Map(state.textures);
|
|
1438
|
-
if (typeof keyOrRecord === "string") {
|
|
1439
|
-
textures.set(keyOrRecord, texture);
|
|
1440
|
-
} else {
|
|
1441
|
-
for (const key in keyOrRecord) textures.set(key, keyOrRecord[key]);
|
|
1442
|
-
}
|
|
1443
|
-
return { textures };
|
|
1444
|
-
});
|
|
1445
|
-
},
|
|
1446
|
-
dispose(key, options) {
|
|
1447
|
-
const state = getState();
|
|
1448
|
-
const refs = state._textureRefs.get(key) ?? 0;
|
|
1449
|
-
if (refs > 0 && !options?.force) {
|
|
1450
|
-
console.warn(
|
|
1451
|
-
`[useTextures] "${key}" still has ${refs} active reference(s); skipping dispose. Pass { force: true } to override.`
|
|
1452
|
-
);
|
|
1453
|
-
return false;
|
|
1539
|
+
function lt(t) {
|
|
1540
|
+
var r = t.tag;
|
|
1541
|
+
if (r === 5 || r === 26 || r === 27 || r === 6) return t;
|
|
1542
|
+
for (t = t.child; t !== null; ) {
|
|
1543
|
+
if (t.tag !== 4 && (r = lt(t), r !== null)) return r;
|
|
1544
|
+
t = t.sibling;
|
|
1454
1545
|
}
|
|
1455
|
-
|
|
1456
|
-
setState((s) => {
|
|
1457
|
-
const textures = new Map(s.textures);
|
|
1458
|
-
textures.delete(key);
|
|
1459
|
-
const nextRefs = new Map(s._textureRefs);
|
|
1460
|
-
nextRefs.delete(key);
|
|
1461
|
-
return { textures, _textureRefs: nextRefs };
|
|
1462
|
-
});
|
|
1463
|
-
return true;
|
|
1464
|
-
},
|
|
1465
|
-
disposeAll() {
|
|
1466
|
-
for (const texture of getState().textures.values()) texture.dispose();
|
|
1467
|
-
setState({ textures: /* @__PURE__ */ new Map(), _textureRefs: /* @__PURE__ */ new Map() });
|
|
1546
|
+
return null;
|
|
1468
1547
|
}
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
1472
|
-
const selected = useThree(subscribe);
|
|
1473
|
-
return selector ? selected : registry;
|
|
1474
|
-
}
|
|
1475
|
-
|
|
1476
|
-
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
1477
|
-
const isLegacy = useThree((s) => s.isLegacy);
|
|
1478
|
-
const size = useThree((s) => s.size);
|
|
1479
|
-
let width;
|
|
1480
|
-
let height;
|
|
1481
|
-
let opts;
|
|
1482
|
-
if (typeof widthOrOptions === "object") {
|
|
1483
|
-
opts = widthOrOptions;
|
|
1484
|
-
} else if (typeof widthOrOptions === "number") {
|
|
1485
|
-
width = widthOrOptions;
|
|
1486
|
-
if (typeof heightOrOptions === "object") {
|
|
1487
|
-
height = widthOrOptions;
|
|
1488
|
-
opts = heightOrOptions;
|
|
1489
|
-
} else if (typeof heightOrOptions === "number") {
|
|
1490
|
-
height = heightOrOptions;
|
|
1491
|
-
opts = options;
|
|
1492
|
-
} else {
|
|
1493
|
-
height = widthOrOptions;
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
return useMemo(() => {
|
|
1497
|
-
const w = width ?? size.width;
|
|
1498
|
-
const h = height ?? size.height;
|
|
1499
|
-
return new WebGLRenderTarget(w, h, opts);
|
|
1500
|
-
}, [width, height, size.width, size.height, opts, isLegacy]);
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
const presetsObj = {
|
|
1504
|
-
apartment: "lebombo_1k.hdr",
|
|
1505
|
-
city: "potsdamer_platz_1k.hdr",
|
|
1506
|
-
dawn: "kiara_1_dawn_1k.hdr",
|
|
1507
|
-
forest: "forest_slope_1k.hdr",
|
|
1508
|
-
lobby: "st_fagans_interior_1k.hdr",
|
|
1509
|
-
night: "dikhololo_night_1k.hdr",
|
|
1510
|
-
park: "rooitou_park_1k.hdr",
|
|
1511
|
-
studio: "studio_small_03_1k.hdr",
|
|
1512
|
-
sunset: "venice_sunset_1k.hdr",
|
|
1513
|
-
warehouse: "empty_warehouse_01_1k.hdr"
|
|
1514
|
-
};
|
|
1515
|
-
|
|
1516
|
-
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
1517
|
-
const isArray = (arr) => Array.isArray(arr);
|
|
1518
|
-
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
1519
|
-
function useEnvironment({
|
|
1520
|
-
files = defaultFiles,
|
|
1521
|
-
path = "",
|
|
1522
|
-
preset = void 0,
|
|
1523
|
-
colorSpace = void 0,
|
|
1524
|
-
extensions
|
|
1525
|
-
} = {}) {
|
|
1526
|
-
if (preset) {
|
|
1527
|
-
validatePreset(preset);
|
|
1528
|
-
files = presetsObj[preset];
|
|
1529
|
-
path = CUBEMAP_ROOT;
|
|
1530
|
-
}
|
|
1531
|
-
const multiFile = isArray(files);
|
|
1532
|
-
const { extension, isCubemap } = getExtension(files);
|
|
1533
|
-
const loader = getLoader(extension);
|
|
1534
|
-
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1535
|
-
const renderer = useThree((state) => state.renderer);
|
|
1536
|
-
useLayoutEffect(() => {
|
|
1537
|
-
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
1538
|
-
function clearGainmapTexture() {
|
|
1539
|
-
useLoader.clear(loader, multiFile ? [files] : files);
|
|
1540
|
-
}
|
|
1541
|
-
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
1542
|
-
}, [extension, files, loader, multiFile, renderer.domElement]);
|
|
1543
|
-
const loaderResult = useLoader(
|
|
1544
|
-
loader,
|
|
1545
|
-
multiFile ? [files] : files,
|
|
1546
|
-
(loader2) => {
|
|
1547
|
-
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
1548
|
-
loader2.setRenderer?.(renderer);
|
|
1549
|
-
}
|
|
1550
|
-
loader2.setPath?.(path);
|
|
1551
|
-
if (extensions) extensions(loader2);
|
|
1552
|
-
}
|
|
1553
|
-
);
|
|
1554
|
-
let texture = multiFile ? (
|
|
1555
|
-
// @ts-ignore
|
|
1556
|
-
loaderResult[0]
|
|
1557
|
-
) : loaderResult;
|
|
1558
|
-
if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
|
|
1559
|
-
texture = texture.renderTarget?.texture;
|
|
1560
|
-
}
|
|
1561
|
-
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
1562
|
-
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
1563
|
-
return texture;
|
|
1564
|
-
}
|
|
1565
|
-
const preloadDefaultOptions = {
|
|
1566
|
-
files: defaultFiles,
|
|
1567
|
-
path: "",
|
|
1568
|
-
preset: void 0,
|
|
1569
|
-
extensions: void 0
|
|
1570
|
-
};
|
|
1571
|
-
useEnvironment.preload = (preloadOptions) => {
|
|
1572
|
-
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
1573
|
-
let { files, path = "" } = options;
|
|
1574
|
-
const { preset, extensions } = options;
|
|
1575
|
-
if (preset) {
|
|
1576
|
-
validatePreset(preset);
|
|
1577
|
-
files = presetsObj[preset];
|
|
1578
|
-
path = CUBEMAP_ROOT;
|
|
1579
|
-
}
|
|
1580
|
-
const { extension } = getExtension(files);
|
|
1581
|
-
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
1582
|
-
throw new Error("useEnvironment: Preloading gainmaps is not supported");
|
|
1583
|
-
}
|
|
1584
|
-
const loader = getLoader(extension);
|
|
1585
|
-
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1586
|
-
useLoader.preload(loader, isArray(files) ? [files] : files, (loader2) => {
|
|
1587
|
-
loader2.setPath?.(path);
|
|
1588
|
-
if (extensions) extensions(loader2);
|
|
1589
|
-
});
|
|
1590
|
-
};
|
|
1591
|
-
const clearDefaultOptins = {
|
|
1592
|
-
files: defaultFiles,
|
|
1593
|
-
preset: void 0
|
|
1594
|
-
};
|
|
1595
|
-
useEnvironment.clear = (clearOptions) => {
|
|
1596
|
-
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
1597
|
-
let { files } = options;
|
|
1598
|
-
const { preset } = options;
|
|
1599
|
-
if (preset) {
|
|
1600
|
-
validatePreset(preset);
|
|
1601
|
-
files = presetsObj[preset];
|
|
1602
|
-
}
|
|
1603
|
-
const { extension } = getExtension(files);
|
|
1604
|
-
const loader = getLoader(extension);
|
|
1605
|
-
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1606
|
-
useLoader.clear(loader, isArray(files) ? [files] : files);
|
|
1607
|
-
};
|
|
1608
|
-
function validatePreset(preset) {
|
|
1609
|
-
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
1610
|
-
}
|
|
1611
|
-
function getExtension(files) {
|
|
1612
|
-
const isCubemap = isArray(files) && files.length === 6;
|
|
1613
|
-
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
1614
|
-
const firstEntry = isArray(files) ? files[0] : files;
|
|
1615
|
-
const extension = isCubemap ? "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1616
|
-
return { extension, isCubemap, isGainmap };
|
|
1617
|
-
}
|
|
1618
|
-
function getLoader(extension) {
|
|
1619
|
-
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
1620
|
-
return loader;
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
function useStore() {
|
|
1624
|
-
const store = useContext(context);
|
|
1625
|
-
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1626
|
-
return store;
|
|
1627
|
-
}
|
|
1628
|
-
function useThree(selector = (state) => state, equalityFn) {
|
|
1629
|
-
return useStore()(selector, equalityFn);
|
|
1630
|
-
}
|
|
1631
|
-
function useInstanceHandle(ref) {
|
|
1632
|
-
const instance = useRef(null);
|
|
1633
|
-
useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
1634
|
-
return instance;
|
|
1635
|
-
}
|
|
1636
|
-
function useGraph(object) {
|
|
1637
|
-
return useMemo(() => buildGraph(object), [object]);
|
|
1638
|
-
}
|
|
1639
|
-
|
|
1640
|
-
const t = 1, o = 8, r = 32, e = 2, i$1 = 268435456;
|
|
1641
|
-
|
|
1642
|
-
let effectId = 0;
|
|
1643
|
-
function addEffect(callback) {
|
|
1644
|
-
notifyDepreciated({
|
|
1645
|
-
heading: "addEffect is deprecated",
|
|
1646
|
-
body: 'Use useFrame(callback, { phase: "start" }) instead.\naddEffect will be removed in a future version.',
|
|
1647
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1648
|
-
});
|
|
1649
|
-
const id = `legacy_effect_${effectId++}`;
|
|
1650
|
-
return getScheduler().registerGlobal("before", id, callback);
|
|
1651
|
-
}
|
|
1652
|
-
function addAfterEffect(callback) {
|
|
1653
|
-
notifyDepreciated({
|
|
1654
|
-
heading: "addAfterEffect is deprecated",
|
|
1655
|
-
body: 'Use useFrame(callback, { phase: "finish" }) instead.\naddAfterEffect will be removed in a future version.',
|
|
1656
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1657
|
-
});
|
|
1658
|
-
const id = `legacy_afterEffect_${effectId++}`;
|
|
1659
|
-
return getScheduler().registerGlobal("after", id, callback);
|
|
1660
|
-
}
|
|
1661
|
-
function addTail(callback) {
|
|
1662
|
-
notifyDepreciated({
|
|
1663
|
-
heading: "addTail is deprecated",
|
|
1664
|
-
body: "Use scheduler.onIdle(callback) instead.\naddTail will be removed in a future version.",
|
|
1665
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
1666
|
-
});
|
|
1667
|
-
return getScheduler().onIdle(callback);
|
|
1668
|
-
}
|
|
1669
|
-
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1670
|
-
getScheduler().invalidate(frames, stackFrames);
|
|
1671
|
-
}
|
|
1672
|
-
function advance(timestamp) {
|
|
1673
|
-
getScheduler().step(timestamp);
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
const version = "10.0.0-alpha.3";
|
|
1677
|
-
const packageData = {
|
|
1678
|
-
version: version};
|
|
1679
|
-
|
|
1680
|
-
function Xb(Tt) {
|
|
1681
|
-
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
1682
|
-
}
|
|
1683
|
-
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
1684
|
-
function Kb() {
|
|
1685
|
-
return _b || (_b = 1, (function(Tt) {
|
|
1686
|
-
Tt.exports = function(m) {
|
|
1687
|
-
function Yn(t, r, a, l) {
|
|
1688
|
-
return new uc(t, r, a, l);
|
|
1689
|
-
}
|
|
1690
|
-
function _d() {
|
|
1691
|
-
}
|
|
1692
|
-
function F(t) {
|
|
1693
|
-
var r = "https://react.dev/errors/" + t;
|
|
1694
|
-
if (1 < arguments.length) {
|
|
1695
|
-
r += "?args[]=" + encodeURIComponent(arguments[1]);
|
|
1696
|
-
for (var a = 2; a < arguments.length; a++) r += "&args[]=" + encodeURIComponent(arguments[a]);
|
|
1697
|
-
}
|
|
1698
|
-
return "Minified React error #" + t + "; visit " + r + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";
|
|
1699
|
-
}
|
|
1700
|
-
function Rd(t) {
|
|
1701
|
-
var r = t, a = t;
|
|
1702
|
-
if (t.alternate) for (; r.return; ) r = r.return;
|
|
1703
|
-
else {
|
|
1704
|
-
t = r;
|
|
1705
|
-
do
|
|
1706
|
-
r = t, (r.flags & 4098) !== 0 && (a = r.return), t = r.return;
|
|
1707
|
-
while (t);
|
|
1708
|
-
}
|
|
1709
|
-
return r.tag === 3 ? a : null;
|
|
1710
|
-
}
|
|
1711
|
-
function du(t) {
|
|
1712
|
-
if (Rd(t) !== t) throw Error(F(188));
|
|
1713
|
-
}
|
|
1714
|
-
function fu(t) {
|
|
1715
|
-
var r = t.alternate;
|
|
1716
|
-
if (!r) {
|
|
1717
|
-
if (r = Rd(t), r === null) throw Error(F(188));
|
|
1718
|
-
return r !== t ? null : t;
|
|
1719
|
-
}
|
|
1720
|
-
for (var a = t, l = r; ; ) {
|
|
1721
|
-
var c = a.return;
|
|
1722
|
-
if (c === null) break;
|
|
1723
|
-
var d = c.alternate;
|
|
1724
|
-
if (d === null) {
|
|
1725
|
-
if (l = c.return, l !== null) {
|
|
1726
|
-
a = l;
|
|
1727
|
-
continue;
|
|
1728
|
-
}
|
|
1729
|
-
break;
|
|
1730
|
-
}
|
|
1731
|
-
if (c.child === d.child) {
|
|
1732
|
-
for (d = c.child; d; ) {
|
|
1733
|
-
if (d === a) return du(c), t;
|
|
1734
|
-
if (d === l) return du(c), r;
|
|
1735
|
-
d = d.sibling;
|
|
1736
|
-
}
|
|
1737
|
-
throw Error(F(188));
|
|
1738
|
-
}
|
|
1739
|
-
if (a.return !== l.return) a = c, l = d;
|
|
1740
|
-
else {
|
|
1741
|
-
for (var h = false, y = c.child; y; ) {
|
|
1742
|
-
if (y === a) {
|
|
1743
|
-
h = true, a = c, l = d;
|
|
1744
|
-
break;
|
|
1745
|
-
}
|
|
1746
|
-
if (y === l) {
|
|
1747
|
-
h = true, l = c, a = d;
|
|
1748
|
-
break;
|
|
1749
|
-
}
|
|
1750
|
-
y = y.sibling;
|
|
1751
|
-
}
|
|
1752
|
-
if (!h) {
|
|
1753
|
-
for (y = d.child; y; ) {
|
|
1754
|
-
if (y === a) {
|
|
1755
|
-
h = true, a = d, l = c;
|
|
1756
|
-
break;
|
|
1757
|
-
}
|
|
1758
|
-
if (y === l) {
|
|
1759
|
-
h = true, l = d, a = c;
|
|
1760
|
-
break;
|
|
1761
|
-
}
|
|
1762
|
-
y = y.sibling;
|
|
1763
|
-
}
|
|
1764
|
-
if (!h) throw Error(F(189));
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
if (a.alternate !== l) throw Error(F(190));
|
|
1768
|
-
}
|
|
1769
|
-
if (a.tag !== 3) throw Error(F(188));
|
|
1770
|
-
return a.stateNode.current === a ? t : r;
|
|
1771
|
-
}
|
|
1772
|
-
function pu(t) {
|
|
1773
|
-
var r = t.tag;
|
|
1774
|
-
if (r === 5 || r === 26 || r === 27 || r === 6) return t;
|
|
1775
|
-
for (t = t.child; t !== null; ) {
|
|
1776
|
-
if (r = pu(t), r !== null) return r;
|
|
1777
|
-
t = t.sibling;
|
|
1778
|
-
}
|
|
1779
|
-
return null;
|
|
1780
|
-
}
|
|
1781
|
-
function lt(t) {
|
|
1782
|
-
var r = t.tag;
|
|
1783
|
-
if (r === 5 || r === 26 || r === 27 || r === 6) return t;
|
|
1784
|
-
for (t = t.child; t !== null; ) {
|
|
1785
|
-
if (t.tag !== 4 && (r = lt(t), r !== null)) return r;
|
|
1786
|
-
t = t.sibling;
|
|
1787
|
-
}
|
|
1788
|
-
return null;
|
|
1789
|
-
}
|
|
1790
|
-
function Fl(t) {
|
|
1791
|
-
return t === null || typeof t != "object" ? null : (t = Pf && t[Pf] || t["@@iterator"], typeof t == "function" ? t : null);
|
|
1548
|
+
function Fl(t) {
|
|
1549
|
+
return t === null || typeof t != "object" ? null : (t = Pf && t[Pf] || t["@@iterator"], typeof t == "function" ? t : null);
|
|
1792
1550
|
}
|
|
1793
1551
|
function hu(t) {
|
|
1794
1552
|
if (t == null) return null;
|
|
@@ -13532,7 +13290,10 @@ function extend(objects) {
|
|
|
13532
13290
|
catalogue[Component] = objects;
|
|
13533
13291
|
return Component;
|
|
13534
13292
|
} else {
|
|
13535
|
-
|
|
13293
|
+
for (const name in objects) {
|
|
13294
|
+
const object = objects[name];
|
|
13295
|
+
if (isConstructor(object)) catalogue[name] = object;
|
|
13296
|
+
}
|
|
13536
13297
|
}
|
|
13537
13298
|
}
|
|
13538
13299
|
function validateInstance(type, props) {
|
|
@@ -13880,7 +13641,7 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13880
13641
|
getRootHostContext: () => NO_CONTEXT,
|
|
13881
13642
|
getChildHostContext: () => NO_CONTEXT,
|
|
13882
13643
|
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
13883
|
-
validateInstance(type, newProps);
|
|
13644
|
+
validateInstance(instance.type, newProps);
|
|
13884
13645
|
let reconstruct = false;
|
|
13885
13646
|
if (instance.type === "primitive" && oldProps.object !== newProps.object) reconstruct = true;
|
|
13886
13647
|
else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
|
|
@@ -13895,162 +13656,491 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13895
13656
|
else delete instance.props.attach;
|
|
13896
13657
|
if (Object.keys(changedProps).length) applyProps(instance.object, changedProps);
|
|
13897
13658
|
}
|
|
13898
|
-
},
|
|
13899
|
-
finalizeInitialChildren: (instance) => {
|
|
13900
|
-
for (const prop in instance.props) {
|
|
13901
|
-
if (isFromRef(instance.props[prop])) return true;
|
|
13659
|
+
},
|
|
13660
|
+
finalizeInitialChildren: (instance) => {
|
|
13661
|
+
for (const prop in instance.props) {
|
|
13662
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
13663
|
+
}
|
|
13664
|
+
return false;
|
|
13665
|
+
},
|
|
13666
|
+
commitMount(instance) {
|
|
13667
|
+
const resolved = {};
|
|
13668
|
+
for (const prop in instance.props) {
|
|
13669
|
+
const value = instance.props[prop];
|
|
13670
|
+
if (isFromRef(value)) {
|
|
13671
|
+
const { [FROM_REF]: ref, transform } = value;
|
|
13672
|
+
if (ref.current != null) resolved[prop] = transform ? transform(ref.current) : ref.current;
|
|
13673
|
+
}
|
|
13674
|
+
}
|
|
13675
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
13676
|
+
},
|
|
13677
|
+
getPublicInstance: (instance) => instance?.object,
|
|
13678
|
+
prepareForCommit: () => null,
|
|
13679
|
+
preparePortalMount: (container) => {
|
|
13680
|
+
const target = container.getState().internal.container ?? container.getState().scene;
|
|
13681
|
+
return prepare(target, container, "", {});
|
|
13682
|
+
},
|
|
13683
|
+
// Reconstructed instances are swapped once all mutations are committed,
|
|
13684
|
+
// before layout effects run so refs point to the new objects
|
|
13685
|
+
resetAfterCommit: flushReconstructedInstances,
|
|
13686
|
+
shouldSetTextContent: () => false,
|
|
13687
|
+
clearContainer: () => false,
|
|
13688
|
+
hideInstance,
|
|
13689
|
+
unhideInstance,
|
|
13690
|
+
createTextInstance: handleTextInstance,
|
|
13691
|
+
hideTextInstance: handleTextInstance,
|
|
13692
|
+
unhideTextInstance: handleTextInstance,
|
|
13693
|
+
// Mirrors react-dom, which flushes discrete work in microtasks
|
|
13694
|
+
supportsMicrotasks: true,
|
|
13695
|
+
scheduleMicrotask,
|
|
13696
|
+
scheduleTimeout: typeof setTimeout === "function" ? setTimeout : void 0,
|
|
13697
|
+
cancelTimeout: typeof clearTimeout === "function" ? clearTimeout : void 0,
|
|
13698
|
+
noTimeout: -1,
|
|
13699
|
+
getInstanceFromNode: () => null,
|
|
13700
|
+
beforeActiveInstanceBlur() {
|
|
13701
|
+
},
|
|
13702
|
+
afterActiveInstanceBlur() {
|
|
13703
|
+
},
|
|
13704
|
+
detachDeletedInstance() {
|
|
13705
|
+
},
|
|
13706
|
+
prepareScopeUpdate() {
|
|
13707
|
+
},
|
|
13708
|
+
getInstanceFromScope: () => null,
|
|
13709
|
+
shouldAttemptEagerTransition: () => false,
|
|
13710
|
+
trackSchedulerEvent: () => {
|
|
13711
|
+
},
|
|
13712
|
+
resolveEventType: () => null,
|
|
13713
|
+
resolveEventTimeStamp: () => -1.1,
|
|
13714
|
+
requestPostPaintCallback() {
|
|
13715
|
+
},
|
|
13716
|
+
maySuspendCommit: () => false,
|
|
13717
|
+
preloadInstance: () => true,
|
|
13718
|
+
// true indicates already loaded
|
|
13719
|
+
suspendInstance() {
|
|
13720
|
+
},
|
|
13721
|
+
waitForCommitToBeReady: () => null,
|
|
13722
|
+
NotPendingTransition: null,
|
|
13723
|
+
// The reconciler types use the internal ReactContext with all the hidden properties
|
|
13724
|
+
// so we have to cast from the public React.Context type
|
|
13725
|
+
HostTransitionContext: /* @__PURE__ */ React.createContext(
|
|
13726
|
+
null
|
|
13727
|
+
),
|
|
13728
|
+
setCurrentUpdatePriority(newPriority) {
|
|
13729
|
+
currentUpdatePriority = newPriority;
|
|
13730
|
+
},
|
|
13731
|
+
getCurrentUpdatePriority() {
|
|
13732
|
+
return currentUpdatePriority;
|
|
13733
|
+
},
|
|
13734
|
+
resolveUpdatePriority() {
|
|
13735
|
+
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13736
|
+
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13737
|
+
if (eventType === void 0) return r;
|
|
13738
|
+
return getEventPriority(eventType);
|
|
13739
|
+
},
|
|
13740
|
+
resetFormInstance() {
|
|
13741
|
+
},
|
|
13742
|
+
// @ts-ignore DefinitelyTyped is not up to date
|
|
13743
|
+
rendererPackageName: "@react-three/fiber",
|
|
13744
|
+
rendererVersion: packageData.version,
|
|
13745
|
+
// 19.2 Reconciler
|
|
13746
|
+
// https://github.com/facebook/react/pull/31975
|
|
13747
|
+
// https://github.com/facebook/react/pull/31999
|
|
13748
|
+
applyViewTransitionName(_instance, _name, _className) {
|
|
13749
|
+
},
|
|
13750
|
+
restoreViewTransitionName(_instance, _props) {
|
|
13751
|
+
},
|
|
13752
|
+
cancelViewTransitionName(_instance, _name, _props) {
|
|
13753
|
+
},
|
|
13754
|
+
cancelRootViewTransitionName(_rootContainer) {
|
|
13755
|
+
},
|
|
13756
|
+
restoreRootViewTransitionName(_rootContainer) {
|
|
13757
|
+
},
|
|
13758
|
+
InstanceMeasurement: null,
|
|
13759
|
+
measureInstance: (_instance) => null,
|
|
13760
|
+
wasInstanceInViewport: (_measurement) => true,
|
|
13761
|
+
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
13762
|
+
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
13763
|
+
// https://github.com/facebook/react/pull/32002
|
|
13764
|
+
// https://github.com/facebook/react/pull/34486
|
|
13765
|
+
suspendOnActiveViewTransition(_state, _container) {
|
|
13766
|
+
},
|
|
13767
|
+
// https://github.com/facebook/react/pull/32451
|
|
13768
|
+
// https://github.com/facebook/react/pull/32760
|
|
13769
|
+
startGestureTransition: () => null,
|
|
13770
|
+
startViewTransition: () => null,
|
|
13771
|
+
stopViewTransition(_transition) {
|
|
13772
|
+
},
|
|
13773
|
+
// https://github.com/facebook/react/pull/32038
|
|
13774
|
+
createViewTransitionInstance: (_name) => null,
|
|
13775
|
+
// https://github.com/facebook/react/pull/32379
|
|
13776
|
+
// https://github.com/facebook/react/pull/32786
|
|
13777
|
+
getCurrentGestureOffset(_provider) {
|
|
13778
|
+
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
13779
|
+
},
|
|
13780
|
+
// https://github.com/facebook/react/pull/32500
|
|
13781
|
+
cloneMutableInstance(instance, _keepChildren) {
|
|
13782
|
+
return instance;
|
|
13783
|
+
},
|
|
13784
|
+
cloneMutableTextInstance(textInstance) {
|
|
13785
|
+
return textInstance;
|
|
13786
|
+
},
|
|
13787
|
+
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
13788
|
+
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
13789
|
+
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
13790
|
+
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
13791
|
+
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
13792
|
+
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
13793
|
+
cloneRootViewTransitionContainer(_rootContainer) {
|
|
13794
|
+
},
|
|
13795
|
+
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
13796
|
+
},
|
|
13797
|
+
// https://github.com/facebook/react/pull/32465
|
|
13798
|
+
createFragmentInstance: (_fiber) => null,
|
|
13799
|
+
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
13800
|
+
},
|
|
13801
|
+
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
13802
|
+
},
|
|
13803
|
+
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
13804
|
+
},
|
|
13805
|
+
// https://github.com/facebook/react/pull/32653
|
|
13806
|
+
measureClonedInstance: (_instance) => null,
|
|
13807
|
+
// https://github.com/facebook/react/pull/32819
|
|
13808
|
+
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
13809
|
+
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
13810
|
+
// https://github.com/facebook/react/pull/34486
|
|
13811
|
+
startSuspendingCommit: () => null,
|
|
13812
|
+
// https://github.com/facebook/react/pull/34522
|
|
13813
|
+
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
13814
|
+
});
|
|
13815
|
+
|
|
13816
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
13817
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
13818
|
+
if (!stack) return false;
|
|
13819
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
13820
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
13821
|
+
}
|
|
13822
|
+
|
|
13823
|
+
const createStore = (invalidate, advance) => {
|
|
13824
|
+
const rootStore = createWithEqualityFn((set, get) => {
|
|
13825
|
+
const position = new Vector3();
|
|
13826
|
+
const defaultTarget = new Vector3();
|
|
13827
|
+
const tempTarget = new Vector3();
|
|
13828
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
13829
|
+
const { width, height, top, left } = size;
|
|
13830
|
+
const aspect = width / height;
|
|
13831
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
13832
|
+
else tempTarget.set(...target);
|
|
13833
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
13834
|
+
if (isOrthographicCamera(camera)) {
|
|
13835
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
13836
|
+
} else {
|
|
13837
|
+
const fov = camera.fov * Math.PI / 180;
|
|
13838
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
13839
|
+
const w = h * (width / height);
|
|
13840
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
13841
|
+
}
|
|
13842
|
+
}
|
|
13843
|
+
let performanceTimeout = void 0;
|
|
13844
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
13845
|
+
const pointer = new Vector2();
|
|
13846
|
+
const rootState = {
|
|
13847
|
+
set,
|
|
13848
|
+
get,
|
|
13849
|
+
// Mock objects that have to be configured
|
|
13850
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
13851
|
+
primaryStore: null,
|
|
13852
|
+
gl: null,
|
|
13853
|
+
renderer: null,
|
|
13854
|
+
camera: null,
|
|
13855
|
+
frustum: new Frustum(),
|
|
13856
|
+
autoUpdateFrustum: true,
|
|
13857
|
+
raycaster: null,
|
|
13858
|
+
events: {
|
|
13859
|
+
priority: 1,
|
|
13860
|
+
enabled: true,
|
|
13861
|
+
connected: false,
|
|
13862
|
+
frameTimedRaycasts: true,
|
|
13863
|
+
alwaysFireOnScroll: true,
|
|
13864
|
+
updateOnFrame: false
|
|
13865
|
+
},
|
|
13866
|
+
scene: null,
|
|
13867
|
+
rootScene: null,
|
|
13868
|
+
xr: null,
|
|
13869
|
+
inspector: null,
|
|
13870
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
13871
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
13872
|
+
textureColorSpace: SRGBColorSpace,
|
|
13873
|
+
isLegacy: false,
|
|
13874
|
+
webGPUSupported: false,
|
|
13875
|
+
isNative: false,
|
|
13876
|
+
controls: null,
|
|
13877
|
+
pointer,
|
|
13878
|
+
mouse: pointer,
|
|
13879
|
+
frameloop: "always",
|
|
13880
|
+
onPointerMissed: void 0,
|
|
13881
|
+
onDragOverMissed: void 0,
|
|
13882
|
+
onDropMissed: void 0,
|
|
13883
|
+
performance: {
|
|
13884
|
+
current: 1,
|
|
13885
|
+
min: 0.5,
|
|
13886
|
+
max: 1,
|
|
13887
|
+
debounce: 200,
|
|
13888
|
+
regress: () => {
|
|
13889
|
+
const state2 = get();
|
|
13890
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
13891
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
13892
|
+
performanceTimeout = setTimeout(
|
|
13893
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
13894
|
+
state2.performance.debounce
|
|
13895
|
+
);
|
|
13896
|
+
}
|
|
13897
|
+
},
|
|
13898
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
13899
|
+
viewport: {
|
|
13900
|
+
initialDpr: 0,
|
|
13901
|
+
dpr: 0,
|
|
13902
|
+
width: 0,
|
|
13903
|
+
height: 0,
|
|
13904
|
+
top: 0,
|
|
13905
|
+
left: 0,
|
|
13906
|
+
aspect: 0,
|
|
13907
|
+
distance: 0,
|
|
13908
|
+
factor: 0,
|
|
13909
|
+
getCurrentViewport
|
|
13910
|
+
},
|
|
13911
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
13912
|
+
setSize: (width, height, top, left) => {
|
|
13913
|
+
const state2 = get();
|
|
13914
|
+
if (width === void 0) {
|
|
13915
|
+
set({ _sizeImperative: false });
|
|
13916
|
+
if (state2._sizeProps) {
|
|
13917
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
13918
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
13919
|
+
const currentSize = state2.size;
|
|
13920
|
+
const newSize = {
|
|
13921
|
+
width: propW ?? currentSize.width,
|
|
13922
|
+
height: propH ?? currentSize.height,
|
|
13923
|
+
top: currentSize.top,
|
|
13924
|
+
left: currentSize.left
|
|
13925
|
+
};
|
|
13926
|
+
set((s) => ({
|
|
13927
|
+
size: newSize,
|
|
13928
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
13929
|
+
}));
|
|
13930
|
+
get().invalidate();
|
|
13931
|
+
}
|
|
13932
|
+
}
|
|
13933
|
+
return;
|
|
13934
|
+
}
|
|
13935
|
+
const w = width;
|
|
13936
|
+
const h = height ?? width;
|
|
13937
|
+
const t = top ?? state2.size.top;
|
|
13938
|
+
const l = left ?? state2.size.left;
|
|
13939
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
13940
|
+
set((s) => ({
|
|
13941
|
+
size,
|
|
13942
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
13943
|
+
_sizeImperative: true
|
|
13944
|
+
}));
|
|
13945
|
+
get().invalidate();
|
|
13946
|
+
},
|
|
13947
|
+
setDpr: (dpr) => set((state2) => {
|
|
13948
|
+
const resolved = calculateDpr(dpr);
|
|
13949
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
13950
|
+
}),
|
|
13951
|
+
setFrameloop: (frameloop = "always") => {
|
|
13952
|
+
const rootId = get().internal.rootId;
|
|
13953
|
+
if (rootId) getScheduler().setRootFrameloop(rootId, frameloop);
|
|
13954
|
+
set(() => ({ frameloop }));
|
|
13955
|
+
},
|
|
13956
|
+
setError: (error) => set(() => ({ error })),
|
|
13957
|
+
error: null,
|
|
13958
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
13959
|
+
uniforms: {},
|
|
13960
|
+
nodes: {},
|
|
13961
|
+
buffers: {},
|
|
13962
|
+
gpuStorage: {},
|
|
13963
|
+
textures: /* @__PURE__ */ new Map(),
|
|
13964
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
13965
|
+
renderPipeline: null,
|
|
13966
|
+
passes: {},
|
|
13967
|
+
_hmrVersion: 0,
|
|
13968
|
+
_sizeImperative: false,
|
|
13969
|
+
_sizeProps: null,
|
|
13970
|
+
previousRoot: void 0,
|
|
13971
|
+
internal: {
|
|
13972
|
+
// Events
|
|
13973
|
+
interaction: [],
|
|
13974
|
+
subscribers: [],
|
|
13975
|
+
// Per-pointer state (new unified structure)
|
|
13976
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
13977
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
13978
|
+
lastEvent: React.createRef(),
|
|
13979
|
+
// Deprecated but kept for backwards compatibility
|
|
13980
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
13981
|
+
initialClick: [0, 0],
|
|
13982
|
+
initialHits: [],
|
|
13983
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
13984
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
13985
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
13986
|
+
// Occlusion system (WebGPU only)
|
|
13987
|
+
occlusionEnabled: false,
|
|
13988
|
+
occlusionObserver: null,
|
|
13989
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
13990
|
+
helperGroup: null,
|
|
13991
|
+
// Updates
|
|
13992
|
+
active: false,
|
|
13993
|
+
frames: 0,
|
|
13994
|
+
priority: 0,
|
|
13995
|
+
subscribe: (ref, priority, store) => {
|
|
13996
|
+
const internal = get().internal;
|
|
13997
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
13998
|
+
internal.subscribers.push({ ref, priority, store });
|
|
13999
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14000
|
+
return () => {
|
|
14001
|
+
const internal2 = get().internal;
|
|
14002
|
+
if (internal2?.subscribers) {
|
|
14003
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14004
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14005
|
+
}
|
|
14006
|
+
};
|
|
14007
|
+
},
|
|
14008
|
+
// Renderer Storage (single source of truth)
|
|
14009
|
+
actualRenderer: null,
|
|
14010
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14011
|
+
scheduler: null,
|
|
14012
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
14013
|
+
renderOverride: null
|
|
14014
|
+
}
|
|
14015
|
+
};
|
|
14016
|
+
return rootState;
|
|
14017
|
+
});
|
|
14018
|
+
const state = rootStore.getState();
|
|
14019
|
+
Object.defineProperty(state, "gl", {
|
|
14020
|
+
get() {
|
|
14021
|
+
const currentState = rootStore.getState();
|
|
14022
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14023
|
+
const stack = new Error().stack || "";
|
|
14024
|
+
if (!isInternalRendererAccess(stack)) {
|
|
14025
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14026
|
+
notifyDepreciated({
|
|
14027
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
14028
|
+
body: "Please use state.renderer instead. state.gl is deprecated and will be removed in future versions.\n\nFor backwards compatibility, state.gl currently maps to state.renderer, but this may cause issues with libraries expecting WebGLRenderer.\n\nAccessed from:\n" + cleanedStack
|
|
14029
|
+
});
|
|
14030
|
+
}
|
|
14031
|
+
}
|
|
14032
|
+
return currentState.internal.actualRenderer;
|
|
14033
|
+
},
|
|
14034
|
+
set(value) {
|
|
14035
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14036
|
+
},
|
|
14037
|
+
enumerable: true,
|
|
14038
|
+
configurable: true
|
|
14039
|
+
});
|
|
14040
|
+
Object.defineProperty(state, "renderer", {
|
|
14041
|
+
get() {
|
|
14042
|
+
return rootStore.getState().internal.actualRenderer;
|
|
14043
|
+
},
|
|
14044
|
+
set(value) {
|
|
14045
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14046
|
+
},
|
|
14047
|
+
enumerable: true,
|
|
14048
|
+
configurable: true
|
|
14049
|
+
});
|
|
14050
|
+
let oldScene = state.scene;
|
|
14051
|
+
rootStore.subscribe(() => {
|
|
14052
|
+
const currentState = rootStore.getState();
|
|
14053
|
+
const { scene, rootScene, set } = currentState;
|
|
14054
|
+
if (scene !== oldScene) {
|
|
14055
|
+
oldScene = scene;
|
|
14056
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
14057
|
+
set({ rootScene: scene });
|
|
14058
|
+
}
|
|
14059
|
+
}
|
|
14060
|
+
});
|
|
14061
|
+
let oldSize = state.size;
|
|
14062
|
+
let oldDpr = state.viewport.dpr;
|
|
14063
|
+
let oldCamera = state.camera;
|
|
14064
|
+
rootStore.subscribe(() => {
|
|
14065
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14066
|
+
const actualRenderer = internal.actualRenderer;
|
|
14067
|
+
const canvasTarget = internal.canvasTarget;
|
|
14068
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14069
|
+
oldSize = size;
|
|
14070
|
+
oldDpr = viewport.dpr;
|
|
14071
|
+
updateCamera(camera, size);
|
|
14072
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14073
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14074
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
14075
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14076
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
13902
14077
|
}
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
14078
|
+
if (camera !== oldCamera) {
|
|
14079
|
+
oldCamera = camera;
|
|
14080
|
+
const { rootScene } = rootStore.getState();
|
|
14081
|
+
if (camera && rootScene && !camera.parent) {
|
|
14082
|
+
rootScene.add(camera);
|
|
14083
|
+
}
|
|
14084
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14085
|
+
const currentState = rootStore.getState();
|
|
14086
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
14087
|
+
updateFrustum(camera, currentState.frustum);
|
|
13912
14088
|
}
|
|
13913
14089
|
}
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
),
|
|
13967
|
-
|
|
13968
|
-
currentUpdatePriority = newPriority;
|
|
13969
|
-
},
|
|
13970
|
-
getCurrentUpdatePriority() {
|
|
13971
|
-
return currentUpdatePriority;
|
|
13972
|
-
},
|
|
13973
|
-
resolveUpdatePriority() {
|
|
13974
|
-
if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
|
|
13975
|
-
const eventType = typeof window !== "undefined" ? window.event?.type : void 0;
|
|
13976
|
-
if (eventType === void 0) return r;
|
|
13977
|
-
return getEventPriority(eventType);
|
|
13978
|
-
},
|
|
13979
|
-
resetFormInstance() {
|
|
13980
|
-
},
|
|
13981
|
-
// @ts-ignore DefinitelyTyped is not up to date
|
|
13982
|
-
rendererPackageName: "@react-three/fiber",
|
|
13983
|
-
rendererVersion: packageData.version,
|
|
13984
|
-
// 19.2 Reconciler
|
|
13985
|
-
// https://github.com/facebook/react/pull/31975
|
|
13986
|
-
// https://github.com/facebook/react/pull/31999
|
|
13987
|
-
applyViewTransitionName(_instance, _name, _className) {
|
|
13988
|
-
},
|
|
13989
|
-
restoreViewTransitionName(_instance, _props) {
|
|
13990
|
-
},
|
|
13991
|
-
cancelViewTransitionName(_instance, _name, _props) {
|
|
13992
|
-
},
|
|
13993
|
-
cancelRootViewTransitionName(_rootContainer) {
|
|
13994
|
-
},
|
|
13995
|
-
restoreRootViewTransitionName(_rootContainer) {
|
|
13996
|
-
},
|
|
13997
|
-
InstanceMeasurement: null,
|
|
13998
|
-
measureInstance: (_instance) => null,
|
|
13999
|
-
wasInstanceInViewport: (_measurement) => true,
|
|
14000
|
-
hasInstanceChanged: (_oldMeasurement, _newMeasurement) => false,
|
|
14001
|
-
hasInstanceAffectedParent: (_oldMeasurement, _newMeasurement) => false,
|
|
14002
|
-
// https://github.com/facebook/react/pull/32002
|
|
14003
|
-
// https://github.com/facebook/react/pull/34486
|
|
14004
|
-
suspendOnActiveViewTransition(_state, _container) {
|
|
14005
|
-
},
|
|
14006
|
-
// https://github.com/facebook/react/pull/32451
|
|
14007
|
-
// https://github.com/facebook/react/pull/32760
|
|
14008
|
-
startGestureTransition: () => null,
|
|
14009
|
-
startViewTransition: () => null,
|
|
14010
|
-
stopViewTransition(_transition) {
|
|
14011
|
-
},
|
|
14012
|
-
// https://github.com/facebook/react/pull/32038
|
|
14013
|
-
createViewTransitionInstance: (_name) => null,
|
|
14014
|
-
// https://github.com/facebook/react/pull/32379
|
|
14015
|
-
// https://github.com/facebook/react/pull/32786
|
|
14016
|
-
getCurrentGestureOffset(_provider) {
|
|
14017
|
-
throw new Error("startGestureTransition is not yet supported in react-three-fiber.");
|
|
14018
|
-
},
|
|
14019
|
-
// https://github.com/facebook/react/pull/32500
|
|
14020
|
-
cloneMutableInstance(instance, _keepChildren) {
|
|
14021
|
-
return instance;
|
|
14022
|
-
},
|
|
14023
|
-
cloneMutableTextInstance(textInstance) {
|
|
14024
|
-
return textInstance;
|
|
14025
|
-
},
|
|
14026
|
-
// React 19.2 added these for root-level view transitions. They only run for hosts that opt into
|
|
14027
|
-
// view transitions by returning a container from cloneRootViewTransitionContainer; R3F renders
|
|
14028
|
-
// into a WebGL/WebGPU canvas, where cloning the root has no meaning, so we never opt in and
|
|
14029
|
-
// React never calls them. They stay as no-ops rather than throws: the host config is shared by
|
|
14030
|
-
// every root, and a throw here would turn a React-internal probe into a hard crash for users.
|
|
14031
|
-
// Guarded by a test asserting a full render + unmount never reaches them.
|
|
14032
|
-
cloneRootViewTransitionContainer(_rootContainer) {
|
|
14033
|
-
},
|
|
14034
|
-
removeRootViewTransitionClone(_rootContainer, _clone) {
|
|
14035
|
-
},
|
|
14036
|
-
// https://github.com/facebook/react/pull/32465
|
|
14037
|
-
createFragmentInstance: (_fiber) => null,
|
|
14038
|
-
updateFragmentInstanceFiber(_fiber, _instance) {
|
|
14039
|
-
},
|
|
14040
|
-
commitNewChildToFragmentInstance(_child, _fragmentInstance) {
|
|
14041
|
-
},
|
|
14042
|
-
deleteChildFromFragmentInstance(_child, _fragmentInstance) {
|
|
14043
|
-
},
|
|
14044
|
-
// https://github.com/facebook/react/pull/32653
|
|
14045
|
-
measureClonedInstance: (_instance) => null,
|
|
14046
|
-
// https://github.com/facebook/react/pull/32819
|
|
14047
|
-
maySuspendCommitOnUpdate: (_type, _oldProps, _newProps) => false,
|
|
14048
|
-
maySuspendCommitInSyncRender: (_type, _props) => false,
|
|
14049
|
-
// https://github.com/facebook/react/pull/34486
|
|
14050
|
-
startSuspendingCommit: () => null,
|
|
14051
|
-
// https://github.com/facebook/react/pull/34522
|
|
14052
|
-
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14053
|
-
});
|
|
14090
|
+
});
|
|
14091
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
14092
|
+
return rootStore;
|
|
14093
|
+
};
|
|
14094
|
+
|
|
14095
|
+
const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
|
|
14096
|
+
function getRegistry() {
|
|
14097
|
+
return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
|
|
14098
|
+
extensions: /* @__PURE__ */ new Map(),
|
|
14099
|
+
roots: /* @__PURE__ */ new Set(),
|
|
14100
|
+
applied: /* @__PURE__ */ new WeakMap()
|
|
14101
|
+
});
|
|
14102
|
+
}
|
|
14103
|
+
function setupRoot(registry, store, extension) {
|
|
14104
|
+
let applied = registry.applied.get(store);
|
|
14105
|
+
if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
|
|
14106
|
+
if (applied.has(extension.name)) return;
|
|
14107
|
+
applied.set(extension.name, extension);
|
|
14108
|
+
const patch = extension.setup?.(store);
|
|
14109
|
+
if (patch) store.setState(patch);
|
|
14110
|
+
}
|
|
14111
|
+
function registerRootExtension(extension) {
|
|
14112
|
+
const registry = getRegistry();
|
|
14113
|
+
registry.extensions.set(extension.name, extension);
|
|
14114
|
+
for (const store of registry.roots) setupRoot(registry, store, extension);
|
|
14115
|
+
return () => {
|
|
14116
|
+
if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
|
|
14117
|
+
};
|
|
14118
|
+
}
|
|
14119
|
+
function setRenderOverride(store, render) {
|
|
14120
|
+
store.getState().internal.renderOverride = render;
|
|
14121
|
+
}
|
|
14122
|
+
function attachRootExtensions(store) {
|
|
14123
|
+
const registry = getRegistry();
|
|
14124
|
+
registry.roots.add(store);
|
|
14125
|
+
for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
|
|
14126
|
+
}
|
|
14127
|
+
function current(registry, setUpBy) {
|
|
14128
|
+
return registry.extensions.get(setUpBy.name) ?? setUpBy;
|
|
14129
|
+
}
|
|
14130
|
+
function detachRootExtensions(store) {
|
|
14131
|
+
const registry = getRegistry();
|
|
14132
|
+
if (!registry.roots.delete(store)) return;
|
|
14133
|
+
const applied = registry.applied.get(store);
|
|
14134
|
+
registry.applied.delete(store);
|
|
14135
|
+
if (!applied) return;
|
|
14136
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
|
|
14137
|
+
}
|
|
14138
|
+
function notifyRootExtensionsHmr(store) {
|
|
14139
|
+
const registry = getRegistry();
|
|
14140
|
+
const applied = registry.applied.get(store);
|
|
14141
|
+
if (!applied) return;
|
|
14142
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
|
|
14143
|
+
}
|
|
14054
14144
|
|
|
14055
14145
|
const isRenderer = (def) => !!def?.render;
|
|
14056
14146
|
const _roots = /* @__PURE__ */ new Map();
|
|
@@ -14285,7 +14375,7 @@ function createRoot(canvas) {
|
|
|
14285
14375
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14286
14376
|
const state2 = store.getState();
|
|
14287
14377
|
if (state2.frameloop === "never") return;
|
|
14288
|
-
advance(timestamp);
|
|
14378
|
+
advance(timestamp, true, state2);
|
|
14289
14379
|
};
|
|
14290
14380
|
const actualRenderer = state.internal.actualRenderer;
|
|
14291
14381
|
const handleSessionChange = () => {
|
|
@@ -14293,7 +14383,7 @@ function createRoot(canvas) {
|
|
|
14293
14383
|
const renderer2 = state2.internal.actualRenderer;
|
|
14294
14384
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14295
14385
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14296
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14386
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14297
14387
|
};
|
|
14298
14388
|
const xr = {
|
|
14299
14389
|
connect() {
|
|
@@ -14375,14 +14465,23 @@ function createRoot(canvas) {
|
|
|
14375
14465
|
const newRootId = canvasId || scheduler.generateRootId();
|
|
14376
14466
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14377
14467
|
getState: () => store.getState(),
|
|
14378
|
-
onError: (err) => store.getState().setError(err)
|
|
14468
|
+
onError: (err) => store.getState().setError(err),
|
|
14469
|
+
frameloop: store.getState().frameloop,
|
|
14470
|
+
before: schedulerConfig?.before,
|
|
14471
|
+
after: schedulerConfig?.after,
|
|
14472
|
+
order: schedulerConfig?.order
|
|
14379
14473
|
});
|
|
14380
14474
|
const unregisterCanvasTarget = scheduler.register(
|
|
14381
14475
|
() => {
|
|
14382
14476
|
const state2 = store.getState();
|
|
14383
|
-
|
|
14477
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14478
|
+
if (canvasTarget) {
|
|
14384
14479
|
const renderer2 = state2.internal.actualRenderer;
|
|
14385
|
-
renderer2.setCanvasTarget(
|
|
14480
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14481
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14482
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14483
|
+
renderer2.backend?.updateSize?.();
|
|
14484
|
+
}
|
|
14386
14485
|
}
|
|
14387
14486
|
},
|
|
14388
14487
|
{
|
|
@@ -14438,7 +14537,8 @@ function createRoot(canvas) {
|
|
|
14438
14537
|
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
14439
14538
|
if (userHandlesRender || state2.internal.priority) return;
|
|
14440
14539
|
try {
|
|
14441
|
-
|
|
14540
|
+
const renderOverride = state2.internal.renderOverride;
|
|
14541
|
+
if (renderOverride) renderOverride();
|
|
14442
14542
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
14443
14543
|
} catch (error) {
|
|
14444
14544
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -14451,8 +14551,7 @@ function createRoot(canvas) {
|
|
|
14451
14551
|
phase: "render",
|
|
14452
14552
|
system: true,
|
|
14453
14553
|
// Internal flag: this is a system job, not user-controlled
|
|
14454
|
-
//
|
|
14455
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14554
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14456
14555
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14457
14556
|
}
|
|
14458
14557
|
);
|
|
@@ -14471,8 +14570,22 @@ function createRoot(canvas) {
|
|
|
14471
14570
|
scheduler
|
|
14472
14571
|
}
|
|
14473
14572
|
}));
|
|
14573
|
+
} else {
|
|
14574
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14575
|
+
if (constraintsChanged) {
|
|
14576
|
+
scheduler.setRootConstraints(rootId, {
|
|
14577
|
+
before: schedulerConfig?.before,
|
|
14578
|
+
after: schedulerConfig?.after
|
|
14579
|
+
});
|
|
14580
|
+
}
|
|
14581
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14582
|
+
scheduler.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14583
|
+
}
|
|
14474
14584
|
}
|
|
14475
|
-
|
|
14585
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14586
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14587
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14588
|
+
attachRootExtensions(store);
|
|
14476
14589
|
onCreated = onCreatedCallback;
|
|
14477
14590
|
configured = true;
|
|
14478
14591
|
resolve();
|
|
@@ -14514,18 +14627,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14514
14627
|
const fiber = root?.fiber;
|
|
14515
14628
|
if (fiber) {
|
|
14516
14629
|
const state = root?.store.getState();
|
|
14517
|
-
if (state)
|
|
14630
|
+
if (state) {
|
|
14631
|
+
state.internal.active = false;
|
|
14632
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14633
|
+
if (unregisterRoot) {
|
|
14634
|
+
unregisterRoot();
|
|
14635
|
+
state.internal.unregisterRoot = void 0;
|
|
14636
|
+
}
|
|
14637
|
+
}
|
|
14518
14638
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14639
|
+
if (root?.store) detachRootExtensions(root.store);
|
|
14519
14640
|
if (state) {
|
|
14520
14641
|
setTimeout(() => {
|
|
14521
14642
|
try {
|
|
14522
14643
|
const renderer = state.internal.actualRenderer;
|
|
14523
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14524
|
-
if (unregisterRoot) unregisterRoot();
|
|
14525
14644
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14526
14645
|
if (unregisterPrimary) unregisterPrimary();
|
|
14527
14646
|
const canvasTarget = state.internal.canvasTarget;
|
|
14528
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14647
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14529
14648
|
state.events.disconnect?.();
|
|
14530
14649
|
cleanupHelperGroup(root.store);
|
|
14531
14650
|
if (state.isLegacy && renderer) {
|
|
@@ -14595,11 +14714,24 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14595
14714
|
}
|
|
14596
14715
|
};
|
|
14597
14716
|
}, [portalScene, container, injectScene]);
|
|
14717
|
+
const lastRootState = useRef(null);
|
|
14598
14718
|
const inject = useMutableCallback((rootState, injectState) => {
|
|
14719
|
+
const followed = {};
|
|
14720
|
+
const lastRoot = lastRootState.current;
|
|
14721
|
+
if (lastRoot) {
|
|
14722
|
+
for (const key in rootState) {
|
|
14723
|
+
const field = key;
|
|
14724
|
+
const changed = rootState[field] !== lastRoot[field];
|
|
14725
|
+
const inherited = !(key in rest) && injectState[field] === lastRoot[field];
|
|
14726
|
+
if (changed && inherited) followed[field] = rootState[field];
|
|
14727
|
+
}
|
|
14728
|
+
}
|
|
14729
|
+
lastRootState.current = rootState;
|
|
14599
14730
|
const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
|
|
14600
14731
|
let viewport = void 0;
|
|
14601
|
-
|
|
14602
|
-
|
|
14732
|
+
const portalCamera = followed.camera ?? injectState.camera;
|
|
14733
|
+
if (portalCamera && (size || injectState.size)) {
|
|
14734
|
+
const camera = portalCamera;
|
|
14603
14735
|
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), resolvedSize);
|
|
14604
14736
|
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14605
14737
|
}
|
|
@@ -14608,6 +14740,7 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14608
14740
|
// The intersect consists of the previous root state
|
|
14609
14741
|
...rootState,
|
|
14610
14742
|
...injectState,
|
|
14743
|
+
...followed,
|
|
14611
14744
|
// Portals have their own scene - always a real THREE.Scene (injected if needed)
|
|
14612
14745
|
scene: portalScene,
|
|
14613
14746
|
// rootScene always points to the actual THREE.Scene, even inside portals
|
|
@@ -14666,16 +14799,11 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14666
14799
|
const oldbg = target.background;
|
|
14667
14800
|
const oldenv = target.environment;
|
|
14668
14801
|
const oldSceneProps = {
|
|
14669
|
-
// @ts-ignore
|
|
14670
14802
|
backgroundBlurriness: target.backgroundBlurriness,
|
|
14671
|
-
// @ts-ignore
|
|
14672
14803
|
backgroundIntensity: target.backgroundIntensity,
|
|
14673
|
-
|
|
14674
|
-
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
14675
|
-
// @ts-ignore
|
|
14804
|
+
backgroundRotation: target.backgroundRotation.clone(),
|
|
14676
14805
|
environmentIntensity: target.environmentIntensity,
|
|
14677
|
-
|
|
14678
|
-
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
14806
|
+
environmentRotation: target.environmentRotation.clone()
|
|
14679
14807
|
};
|
|
14680
14808
|
if (background !== "only") target.environment = texture;
|
|
14681
14809
|
if (background) target.background = texture;
|
|
@@ -14687,7 +14815,7 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14687
14815
|
};
|
|
14688
14816
|
}
|
|
14689
14817
|
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
14690
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14818
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14691
14819
|
React.useLayoutEffect(() => {
|
|
14692
14820
|
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
14693
14821
|
});
|
|
@@ -14705,7 +14833,7 @@ function EnvironmentCube({
|
|
|
14705
14833
|
...rest
|
|
14706
14834
|
}) {
|
|
14707
14835
|
const texture = useEnvironment(rest);
|
|
14708
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14836
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14709
14837
|
React.useLayoutEffect(() => {
|
|
14710
14838
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
14711
14839
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -14742,9 +14870,9 @@ function EnvironmentPortal({
|
|
|
14742
14870
|
preset = void 0,
|
|
14743
14871
|
extensions
|
|
14744
14872
|
}) {
|
|
14745
|
-
const renderer = useThree((state) => state.renderer);
|
|
14746
|
-
const isLegacy = useThree((state) => state.isLegacy);
|
|
14747
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14873
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
14874
|
+
const isLegacy = useThree$1((state) => state.isLegacy);
|
|
14875
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14748
14876
|
const camera = React.useRef(null);
|
|
14749
14877
|
const [virtualScene] = React.useState(() => new Scene());
|
|
14750
14878
|
const fbo = React.useMemo(() => {
|
|
@@ -14788,7 +14916,7 @@ function EnvironmentPortal({
|
|
|
14788
14916
|
environmentRotation
|
|
14789
14917
|
]);
|
|
14790
14918
|
let count = 1;
|
|
14791
|
-
useFrame(() => {
|
|
14919
|
+
useFrame$1(() => {
|
|
14792
14920
|
if (frames === Infinity || count < frames) {
|
|
14793
14921
|
const autoClear = renderer.autoClear;
|
|
14794
14922
|
renderer.autoClear = true;
|
|
@@ -14828,7 +14956,7 @@ function EnvironmentGround(props) {
|
|
|
14828
14956
|
] });
|
|
14829
14957
|
}
|
|
14830
14958
|
function EnvironmentColor({ color, scene }) {
|
|
14831
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14959
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14832
14960
|
React.useLayoutEffect(() => {
|
|
14833
14961
|
if (color === void 0) return;
|
|
14834
14962
|
const target = resolveScene(scene || defaultScene);
|
|
@@ -14900,38 +15028,6 @@ function parseRendererConfig(rendererProp) {
|
|
|
14900
15028
|
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
14901
15029
|
}
|
|
14902
15030
|
|
|
14903
|
-
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
14904
|
-
const registries = /* @__PURE__ */ new WeakMap();
|
|
14905
|
-
function getKindRegistry(store, kind) {
|
|
14906
|
-
let registry = registries.get(store);
|
|
14907
|
-
if (!registry) {
|
|
14908
|
-
registry = {
|
|
14909
|
-
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14910
|
-
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14911
|
-
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14912
|
-
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
14913
|
-
};
|
|
14914
|
-
registries.set(store, registry);
|
|
14915
|
-
}
|
|
14916
|
-
return registry[kind];
|
|
14917
|
-
}
|
|
14918
|
-
function invalidateResource(store, kind, scopeKey) {
|
|
14919
|
-
const registry = getKindRegistry(store, kind);
|
|
14920
|
-
{
|
|
14921
|
-
registry.valid.clear();
|
|
14922
|
-
registry.staged.clear();
|
|
14923
|
-
}
|
|
14924
|
-
}
|
|
14925
|
-
function invalidateAllResources(store) {
|
|
14926
|
-
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
14927
|
-
}
|
|
14928
|
-
|
|
14929
|
-
function clearHmrCaches(store) {
|
|
14930
|
-
const primary = store.getState().primaryStore ?? store;
|
|
14931
|
-
invalidateAllResources(primary);
|
|
14932
|
-
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
14933
|
-
}
|
|
14934
|
-
|
|
14935
15031
|
function CanvasImpl({
|
|
14936
15032
|
ref,
|
|
14937
15033
|
children,
|
|
@@ -14969,9 +15065,9 @@ function CanvasImpl({
|
|
|
14969
15065
|
React.useMemo(() => extend(THREE), []);
|
|
14970
15066
|
const Bridge = useBridge();
|
|
14971
15067
|
const backgroundProps = React.useMemo(() => parseBackground(background), [background]);
|
|
14972
|
-
const
|
|
15068
|
+
const [hasInitialSize, setHasInitialSize] = React.useState(false);
|
|
14973
15069
|
const measureConfig = React.useMemo(() => {
|
|
14974
|
-
if (!
|
|
15070
|
+
if (!hasInitialSize) {
|
|
14975
15071
|
return {
|
|
14976
15072
|
...resize,
|
|
14977
15073
|
scroll: resize?.scroll ?? true,
|
|
@@ -14983,7 +15079,7 @@ function CanvasImpl({
|
|
|
14983
15079
|
debounce: { scroll: 50, resize: 0 },
|
|
14984
15080
|
...resize
|
|
14985
15081
|
};
|
|
14986
|
-
}, [
|
|
15082
|
+
}, [hasInitialSize, resize]);
|
|
14987
15083
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
14988
15084
|
const effectiveSize = React.useMemo(() => {
|
|
14989
15085
|
let w = width ?? containerRect.width;
|
|
@@ -14999,9 +15095,7 @@ function CanvasImpl({
|
|
|
14999
15095
|
left: containerRect.left
|
|
15000
15096
|
};
|
|
15001
15097
|
}, [width, height, containerRect, forceEven]);
|
|
15002
|
-
if (!
|
|
15003
|
-
hasInitialSizeRef.current = true;
|
|
15004
|
-
}
|
|
15098
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15005
15099
|
const canvasRef = React.useRef(null);
|
|
15006
15100
|
const divRef = React.useRef(null);
|
|
15007
15101
|
React.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15115,6 +15209,7 @@ function CanvasImpl({
|
|
|
15115
15209
|
const canvas = canvasRef.current;
|
|
15116
15210
|
if (canvas) {
|
|
15117
15211
|
return () => {
|
|
15212
|
+
if (canvas.isConnected) return;
|
|
15118
15213
|
unmountComponentAtNode(canvas);
|
|
15119
15214
|
root.current = null;
|
|
15120
15215
|
};
|
|
@@ -15127,7 +15222,7 @@ function CanvasImpl({
|
|
|
15127
15222
|
const handleHMR = () => {
|
|
15128
15223
|
queueMicrotask(() => {
|
|
15129
15224
|
const rootEntry = _roots.get(canvas);
|
|
15130
|
-
if (rootEntry?.store)
|
|
15225
|
+
if (rootEntry?.store) notifyRootExtensionsHmr(rootEntry.store);
|
|
15131
15226
|
});
|
|
15132
15227
|
};
|
|
15133
15228
|
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
@@ -15173,10 +15268,13 @@ function CanvasImpl({
|
|
|
15173
15268
|
}
|
|
15174
15269
|
);
|
|
15175
15270
|
}
|
|
15176
|
-
function Canvas(props) {
|
|
15271
|
+
function Canvas$1(props) {
|
|
15177
15272
|
return /* @__PURE__ */ jsx(FiberProvider, { children: /* @__PURE__ */ jsx(CanvasImpl, { ...props }) });
|
|
15178
15273
|
}
|
|
15179
15274
|
|
|
15180
15275
|
extend(THREE);
|
|
15276
|
+
const useThree = useThree$1;
|
|
15277
|
+
const useFrame = useFrame$1;
|
|
15278
|
+
const Canvas = Canvas$1;
|
|
15181
15279
|
|
|
15182
|
-
export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Texture, _roots, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef$1 as isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, reconciler, registerPrimary, removeInteractivity, resolve, swapInteractivity, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree, waitForPrimary };
|
|
15280
|
+
export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Texture, _roots, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef$1 as isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, reconciler, registerPrimary, registerRootExtension, removeInteractivity, resolve, setRenderOverride, swapInteractivity, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree, waitForPrimary };
|