@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/webgpu/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as webgpu from 'three/webgpu';
|
|
2
|
-
import { CubeRenderTarget, RenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType,
|
|
2
|
+
import { CubeRenderTarget, RenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, ShaderMaterial, Uniform, SRGBColorSpace, RGBAFormat, UnsignedByteType, TextureLoader, Texture as Texture$1, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Vector3, Vector2, CanvasTarget, Raycaster, OrthographicCamera, PerspectiveCamera, Scene, PCFShadowMap, VSMShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGPURenderer, HalfFloatType, Color, Vector4, RenderPipeline } from 'three/webgpu';
|
|
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';
|
|
@@ -303,7 +304,6 @@ function prepare(target, root, type, props) {
|
|
|
303
304
|
}
|
|
304
305
|
function invalidateInstance(instance) {
|
|
305
306
|
if (!instance.parent) return;
|
|
306
|
-
instance.props.onUpdate?.(instance.object);
|
|
307
307
|
const state = instance.root?.getState?.();
|
|
308
308
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
309
309
|
}
|
|
@@ -519,8 +519,10 @@ function hasVisibilityHandlers(handlers) {
|
|
|
519
519
|
}
|
|
520
520
|
|
|
521
521
|
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
522
|
-
function fromRef(ref) {
|
|
523
|
-
|
|
522
|
+
function fromRef(ref, transform) {
|
|
523
|
+
const marker = { [FROM_REF]: ref };
|
|
524
|
+
if (transform) marker.transform = transform;
|
|
525
|
+
return marker;
|
|
524
526
|
}
|
|
525
527
|
function isFromRef(value) {
|
|
526
528
|
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
@@ -534,6 +536,63 @@ function isOnce(value) {
|
|
|
534
536
|
return value !== null && typeof value === "object" && ONCE in value;
|
|
535
537
|
}
|
|
536
538
|
|
|
539
|
+
const shownNotices = /* @__PURE__ */ new Set();
|
|
540
|
+
function notifyDepreciated({ heading, body, link }) {
|
|
541
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (shownNotices.has(heading)) return;
|
|
545
|
+
shownNotices.add(heading);
|
|
546
|
+
const caller = getCallerFrame();
|
|
547
|
+
if (caller) {
|
|
548
|
+
console.log();
|
|
549
|
+
}
|
|
550
|
+
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
551
|
+
if (caller) {
|
|
552
|
+
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
553
|
+
}
|
|
554
|
+
if (body || link) {
|
|
555
|
+
let message = "";
|
|
556
|
+
if (body) message += body;
|
|
557
|
+
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
558
|
+
console.warn(`%c${message}`, "font-weight: bold;");
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function getCallerFrame(depth = 3) {
|
|
562
|
+
const stack = new Error().stack;
|
|
563
|
+
if (!stack) return null;
|
|
564
|
+
const lines = stack.split("\n");
|
|
565
|
+
const frame = lines[depth];
|
|
566
|
+
if (!frame) return null;
|
|
567
|
+
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
568
|
+
if (!match) {
|
|
569
|
+
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
570
|
+
}
|
|
571
|
+
if (!match) return null;
|
|
572
|
+
const [, fn, url, line] = match;
|
|
573
|
+
return {
|
|
574
|
+
functionName: fn ?? "<anonymous>",
|
|
575
|
+
location: formatLocation(url, Number(line))
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function formatLocation(url, line) {
|
|
579
|
+
const clean = url.split("?")[0];
|
|
580
|
+
const file = clean.split("/").pop() ?? clean;
|
|
581
|
+
return `${file}:${line}`;
|
|
582
|
+
}
|
|
583
|
+
function notifyAlpha({ message, link }) {
|
|
584
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
if (shownNotices.has(message)) return;
|
|
588
|
+
shownNotices.add(message);
|
|
589
|
+
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
590
|
+
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
591
|
+
{
|
|
592
|
+
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
537
596
|
const RESERVED_PROPS = [
|
|
538
597
|
"children",
|
|
539
598
|
"key",
|
|
@@ -543,7 +602,6 @@ const RESERVED_PROPS = [
|
|
|
543
602
|
"dispose",
|
|
544
603
|
"attach",
|
|
545
604
|
"object",
|
|
546
|
-
"onUpdate",
|
|
547
605
|
// Behavior flags
|
|
548
606
|
"dispose"
|
|
549
607
|
];
|
|
@@ -621,11 +679,9 @@ function diffProps(instance, newProps) {
|
|
|
621
679
|
for (const prop in instance.props) {
|
|
622
680
|
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
623
681
|
const { root, key } = resolve(instance.object, prop);
|
|
624
|
-
if (
|
|
682
|
+
if (typeof root?.constructor === "function") {
|
|
625
683
|
const ctor = getMemoizedPrototype(root);
|
|
626
684
|
if (!is.und(ctor)) changedProps[prop] = ctor[key];
|
|
627
|
-
} else {
|
|
628
|
-
changedProps[prop] = 0;
|
|
629
685
|
}
|
|
630
686
|
}
|
|
631
687
|
return changedProps;
|
|
@@ -637,6 +693,13 @@ function applyProps(object, props) {
|
|
|
637
693
|
for (const prop in props) {
|
|
638
694
|
const value = props[prop];
|
|
639
695
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
696
|
+
if (prop === "onUpdate") {
|
|
697
|
+
notifyDepreciated({
|
|
698
|
+
heading: "onUpdate is no longer an R3F prop",
|
|
699
|
+
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.",
|
|
700
|
+
link: "https://docs.pmnd.rs/react-three-fiber/migration/v10#onupdate-removed"
|
|
701
|
+
});
|
|
702
|
+
}
|
|
640
703
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
641
704
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
642
705
|
else delete instance.handlers[prop];
|
|
@@ -712,376 +775,47 @@ function applyProps(object, props) {
|
|
|
712
775
|
}
|
|
713
776
|
if (instance?.parent && rootState?.internal && instance.object?.isObject3D && prevHandlers !== instance.eventCount) {
|
|
714
777
|
const object2 = instance.object;
|
|
715
|
-
const index = rootState.internal.interaction.indexOf(object2);
|
|
716
|
-
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
717
|
-
if (instance.eventCount && object2.raycast !== null) {
|
|
718
|
-
rootState.internal.interaction.push(object2);
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
if (instance?.parent && rootState?.internal && instance.object?.isObject3D) {
|
|
722
|
-
const object2 = instance.object;
|
|
723
|
-
const root = findInitialRoot(instance);
|
|
724
|
-
const visibilityHandlers = {
|
|
725
|
-
onFramed: instance.handlers.onFramed,
|
|
726
|
-
onOccluded: instance.handlers.onOccluded,
|
|
727
|
-
onVisible: instance.handlers.onVisible
|
|
728
|
-
};
|
|
729
|
-
if (hasVisibilityHandlers(visibilityHandlers)) {
|
|
730
|
-
if (!updateVisibilityHandlers(root, object2, visibilityHandlers)) {
|
|
731
|
-
registerVisibility(root, object2, visibilityHandlers);
|
|
732
|
-
}
|
|
733
|
-
} else {
|
|
734
|
-
unregisterVisibility(root, object2);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
if (instance && instance.props.attach === void 0) {
|
|
738
|
-
if (instance.object.isBufferGeometry) instance.props.attach = "geometry";
|
|
739
|
-
else if (instance.object.isMaterial) instance.props.attach = "material";
|
|
740
|
-
}
|
|
741
|
-
if (instance) invalidateInstance(instance);
|
|
742
|
-
return object;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
const shownNotices = /* @__PURE__ */ new Set();
|
|
746
|
-
function notifyDepreciated({ heading, body, link }) {
|
|
747
|
-
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
748
|
-
return;
|
|
749
|
-
}
|
|
750
|
-
if (shownNotices.has(heading)) return;
|
|
751
|
-
shownNotices.add(heading);
|
|
752
|
-
const caller = getCallerFrame();
|
|
753
|
-
if (caller) {
|
|
754
|
-
console.log();
|
|
755
|
-
}
|
|
756
|
-
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
757
|
-
if (caller) {
|
|
758
|
-
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
759
|
-
}
|
|
760
|
-
if (body || link) {
|
|
761
|
-
let message = "";
|
|
762
|
-
if (body) message += body;
|
|
763
|
-
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
764
|
-
console.warn(`%c${message}`, "font-weight: bold;");
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
function getCallerFrame(depth = 3) {
|
|
768
|
-
const stack = new Error().stack;
|
|
769
|
-
if (!stack) return null;
|
|
770
|
-
const lines = stack.split("\n");
|
|
771
|
-
const frame = lines[depth];
|
|
772
|
-
if (!frame) return null;
|
|
773
|
-
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
774
|
-
if (!match) {
|
|
775
|
-
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
776
|
-
}
|
|
777
|
-
if (!match) return null;
|
|
778
|
-
const [, fn, url, line] = match;
|
|
779
|
-
return {
|
|
780
|
-
functionName: fn ?? "<anonymous>",
|
|
781
|
-
location: formatLocation(url, Number(line))
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
function formatLocation(url, line) {
|
|
785
|
-
const clean = url.split("?")[0];
|
|
786
|
-
const file = clean.split("/").pop() ?? clean;
|
|
787
|
-
return `${file}:${line}`;
|
|
788
|
-
}
|
|
789
|
-
function notifyAlpha({ message, link }) {
|
|
790
|
-
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
791
|
-
return;
|
|
792
|
-
}
|
|
793
|
-
if (shownNotices.has(message)) return;
|
|
794
|
-
shownNotices.add(message);
|
|
795
|
-
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
796
|
-
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
797
|
-
{
|
|
798
|
-
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
803
|
-
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
804
|
-
if (!stack) return false;
|
|
805
|
-
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
806
|
-
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
810
|
-
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
811
|
-
const createStore = (invalidate, advance) => {
|
|
812
|
-
const rootStore = createWithEqualityFn((set, get) => {
|
|
813
|
-
const position = new Vector3();
|
|
814
|
-
const defaultTarget = new Vector3();
|
|
815
|
-
const tempTarget = new Vector3();
|
|
816
|
-
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
817
|
-
const { width, height, top, left } = size;
|
|
818
|
-
const aspect = width / height;
|
|
819
|
-
if (target.isVector3) tempTarget.copy(target);
|
|
820
|
-
else tempTarget.set(...target);
|
|
821
|
-
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
822
|
-
if (isOrthographicCamera(camera)) {
|
|
823
|
-
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
824
|
-
} else {
|
|
825
|
-
const fov = camera.fov * Math.PI / 180;
|
|
826
|
-
const h = 2 * Math.tan(fov / 2) * distance;
|
|
827
|
-
const w = h * (width / height);
|
|
828
|
-
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
let performanceTimeout = void 0;
|
|
832
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
833
|
-
const pointer = new Vector2();
|
|
834
|
-
const rootState = {
|
|
835
|
-
set,
|
|
836
|
-
get,
|
|
837
|
-
// Mock objects that have to be configured
|
|
838
|
-
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
839
|
-
primaryStore: null,
|
|
840
|
-
gl: null,
|
|
841
|
-
renderer: null,
|
|
842
|
-
camera: null,
|
|
843
|
-
frustum: new Frustum(),
|
|
844
|
-
autoUpdateFrustum: true,
|
|
845
|
-
raycaster: null,
|
|
846
|
-
events: {
|
|
847
|
-
priority: 1,
|
|
848
|
-
enabled: true,
|
|
849
|
-
connected: false,
|
|
850
|
-
frameTimedRaycasts: true,
|
|
851
|
-
alwaysFireOnScroll: true,
|
|
852
|
-
updateOnFrame: false
|
|
853
|
-
},
|
|
854
|
-
scene: null,
|
|
855
|
-
rootScene: null,
|
|
856
|
-
xr: null,
|
|
857
|
-
inspector: null,
|
|
858
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
859
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
860
|
-
textureColorSpace: SRGBColorSpace,
|
|
861
|
-
isLegacy: false,
|
|
862
|
-
webGPUSupported: false,
|
|
863
|
-
isNative: false,
|
|
864
|
-
controls: null,
|
|
865
|
-
pointer,
|
|
866
|
-
mouse: pointer,
|
|
867
|
-
frameloop: "always",
|
|
868
|
-
onPointerMissed: void 0,
|
|
869
|
-
onDragOverMissed: void 0,
|
|
870
|
-
onDropMissed: void 0,
|
|
871
|
-
performance: {
|
|
872
|
-
current: 1,
|
|
873
|
-
min: 0.5,
|
|
874
|
-
max: 1,
|
|
875
|
-
debounce: 200,
|
|
876
|
-
regress: () => {
|
|
877
|
-
const state2 = get();
|
|
878
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
879
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
880
|
-
performanceTimeout = setTimeout(
|
|
881
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
882
|
-
state2.performance.debounce
|
|
883
|
-
);
|
|
884
|
-
}
|
|
885
|
-
},
|
|
886
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
887
|
-
viewport: {
|
|
888
|
-
initialDpr: 0,
|
|
889
|
-
dpr: 0,
|
|
890
|
-
width: 0,
|
|
891
|
-
height: 0,
|
|
892
|
-
top: 0,
|
|
893
|
-
left: 0,
|
|
894
|
-
aspect: 0,
|
|
895
|
-
distance: 0,
|
|
896
|
-
factor: 0,
|
|
897
|
-
getCurrentViewport
|
|
898
|
-
},
|
|
899
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
900
|
-
setSize: (width, height, top, left) => {
|
|
901
|
-
const state2 = get();
|
|
902
|
-
if (width === void 0) {
|
|
903
|
-
set({ _sizeImperative: false });
|
|
904
|
-
if (state2._sizeProps) {
|
|
905
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
906
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
907
|
-
const currentSize = state2.size;
|
|
908
|
-
const newSize = {
|
|
909
|
-
width: propW ?? currentSize.width,
|
|
910
|
-
height: propH ?? currentSize.height,
|
|
911
|
-
top: currentSize.top,
|
|
912
|
-
left: currentSize.left
|
|
913
|
-
};
|
|
914
|
-
set((s) => ({
|
|
915
|
-
size: newSize,
|
|
916
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
917
|
-
}));
|
|
918
|
-
getScheduler().invalidate();
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
return;
|
|
922
|
-
}
|
|
923
|
-
const w = width;
|
|
924
|
-
const h = height ?? width;
|
|
925
|
-
const t = top ?? state2.size.top;
|
|
926
|
-
const l = left ?? state2.size.left;
|
|
927
|
-
const size = { width: w, height: h, top: t, left: l };
|
|
928
|
-
set((s) => ({
|
|
929
|
-
size,
|
|
930
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
931
|
-
_sizeImperative: true
|
|
932
|
-
}));
|
|
933
|
-
getScheduler().invalidate();
|
|
934
|
-
},
|
|
935
|
-
setDpr: (dpr) => set((state2) => {
|
|
936
|
-
const resolved = calculateDpr(dpr);
|
|
937
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
938
|
-
}),
|
|
939
|
-
setFrameloop: (frameloop = "always") => {
|
|
940
|
-
set(() => ({ frameloop }));
|
|
941
|
-
getScheduler().frameloop = frameloop;
|
|
942
|
-
},
|
|
943
|
-
setError: (error) => set(() => ({ error })),
|
|
944
|
-
error: null,
|
|
945
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
946
|
-
uniforms: {},
|
|
947
|
-
nodes: {},
|
|
948
|
-
buffers: {},
|
|
949
|
-
gpuStorage: {},
|
|
950
|
-
textures: /* @__PURE__ */ new Map(),
|
|
951
|
-
_textureRefs: /* @__PURE__ */ new Map(),
|
|
952
|
-
renderPipeline: null,
|
|
953
|
-
passes: {},
|
|
954
|
-
_hmrVersion: 0,
|
|
955
|
-
_sizeImperative: false,
|
|
956
|
-
_sizeProps: null,
|
|
957
|
-
previousRoot: void 0,
|
|
958
|
-
internal: {
|
|
959
|
-
// Events
|
|
960
|
-
interaction: [],
|
|
961
|
-
subscribers: [],
|
|
962
|
-
// Per-pointer state (new unified structure)
|
|
963
|
-
pointerMap: /* @__PURE__ */ new Map(),
|
|
964
|
-
pointerDirty: /* @__PURE__ */ new Map(),
|
|
965
|
-
lastEvent: React.createRef(),
|
|
966
|
-
// Deprecated but kept for backwards compatibility
|
|
967
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
968
|
-
initialClick: [0, 0],
|
|
969
|
-
initialHits: [],
|
|
970
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
971
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
972
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
973
|
-
// Occlusion system (WebGPU only)
|
|
974
|
-
occlusionEnabled: false,
|
|
975
|
-
occlusionObserver: null,
|
|
976
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
977
|
-
helperGroup: null,
|
|
978
|
-
// Updates
|
|
979
|
-
active: false,
|
|
980
|
-
frames: 0,
|
|
981
|
-
priority: 0,
|
|
982
|
-
subscribe: (ref, priority, store) => {
|
|
983
|
-
const internal = get().internal;
|
|
984
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
985
|
-
internal.subscribers.push({ ref, priority, store });
|
|
986
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
987
|
-
return () => {
|
|
988
|
-
const internal2 = get().internal;
|
|
989
|
-
if (internal2?.subscribers) {
|
|
990
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
991
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
992
|
-
}
|
|
993
|
-
};
|
|
994
|
-
},
|
|
995
|
-
// Renderer Storage (single source of truth)
|
|
996
|
-
actualRenderer: null,
|
|
997
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
998
|
-
scheduler: null
|
|
999
|
-
}
|
|
1000
|
-
};
|
|
1001
|
-
return rootState;
|
|
1002
|
-
});
|
|
1003
|
-
const state = rootStore.getState();
|
|
1004
|
-
Object.defineProperty(state, "gl", {
|
|
1005
|
-
get() {
|
|
1006
|
-
const currentState = rootStore.getState();
|
|
1007
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1008
|
-
const stack = new Error().stack || "";
|
|
1009
|
-
if (!isInternalRendererAccess(stack)) {
|
|
1010
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1011
|
-
notifyDepreciated({
|
|
1012
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1013
|
-
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
|
|
1014
|
-
});
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
return currentState.internal.actualRenderer;
|
|
1018
|
-
},
|
|
1019
|
-
set(value) {
|
|
1020
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1021
|
-
},
|
|
1022
|
-
enumerable: true,
|
|
1023
|
-
configurable: true
|
|
1024
|
-
});
|
|
1025
|
-
Object.defineProperty(state, "renderer", {
|
|
1026
|
-
get() {
|
|
1027
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1028
|
-
},
|
|
1029
|
-
set(value) {
|
|
1030
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1031
|
-
},
|
|
1032
|
-
enumerable: true,
|
|
1033
|
-
configurable: true
|
|
1034
|
-
});
|
|
1035
|
-
let oldScene = state.scene;
|
|
1036
|
-
rootStore.subscribe(() => {
|
|
1037
|
-
const currentState = rootStore.getState();
|
|
1038
|
-
const { scene, rootScene, set } = currentState;
|
|
1039
|
-
if (scene !== oldScene) {
|
|
1040
|
-
oldScene = scene;
|
|
1041
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1042
|
-
set({ rootScene: scene });
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1046
|
-
let oldSize = state.size;
|
|
1047
|
-
let oldDpr = state.viewport.dpr;
|
|
1048
|
-
let oldCamera = state.camera;
|
|
1049
|
-
rootStore.subscribe(() => {
|
|
1050
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1051
|
-
const actualRenderer = internal.actualRenderer;
|
|
1052
|
-
const canvasTarget = internal.canvasTarget;
|
|
1053
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1054
|
-
oldSize = size;
|
|
1055
|
-
oldDpr = viewport.dpr;
|
|
1056
|
-
updateCamera(camera, size);
|
|
1057
|
-
if (internal.isSecondary && canvasTarget) {
|
|
1058
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1059
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1060
|
-
} else {
|
|
1061
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1062
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1063
|
-
if (canvasTarget) {
|
|
1064
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1065
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
if (camera !== oldCamera) {
|
|
1070
|
-
oldCamera = camera;
|
|
1071
|
-
const { rootScene } = rootStore.getState();
|
|
1072
|
-
if (camera && rootScene && !camera.parent) {
|
|
1073
|
-
rootScene.add(camera);
|
|
1074
|
-
}
|
|
1075
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1076
|
-
const currentState = rootStore.getState();
|
|
1077
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1078
|
-
updateFrustum(camera, currentState.frustum);
|
|
778
|
+
const index = rootState.internal.interaction.indexOf(object2);
|
|
779
|
+
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
780
|
+
if (instance.eventCount && object2.raycast !== null) {
|
|
781
|
+
rootState.internal.interaction.push(object2);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (instance?.parent && rootState?.internal && instance.object?.isObject3D) {
|
|
785
|
+
const object2 = instance.object;
|
|
786
|
+
const root = findInitialRoot(instance);
|
|
787
|
+
const visibilityHandlers = {
|
|
788
|
+
onFramed: instance.handlers.onFramed,
|
|
789
|
+
onOccluded: instance.handlers.onOccluded,
|
|
790
|
+
onVisible: instance.handlers.onVisible
|
|
791
|
+
};
|
|
792
|
+
if (hasVisibilityHandlers(visibilityHandlers)) {
|
|
793
|
+
if (!updateVisibilityHandlers(root, object2, visibilityHandlers)) {
|
|
794
|
+
registerVisibility(root, object2, visibilityHandlers);
|
|
1079
795
|
}
|
|
796
|
+
} else {
|
|
797
|
+
unregisterVisibility(root, object2);
|
|
1080
798
|
}
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
799
|
+
}
|
|
800
|
+
if (instance && instance.props.attach === void 0) {
|
|
801
|
+
if (instance.object.isBufferGeometry) instance.props.attach = "geometry";
|
|
802
|
+
else if (instance.object.isMaterial) instance.props.attach = "material";
|
|
803
|
+
}
|
|
804
|
+
if (instance) invalidateInstance(instance);
|
|
805
|
+
return object;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
809
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
810
|
+
|
|
811
|
+
function useStore() {
|
|
812
|
+
const store = useContext(context);
|
|
813
|
+
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
814
|
+
return store;
|
|
815
|
+
}
|
|
816
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
817
|
+
return useStore()(selector, equalityFn);
|
|
818
|
+
}
|
|
1085
819
|
|
|
1086
820
|
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
1087
821
|
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
@@ -1126,7 +860,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1126
860
|
const results = cacheKeys.map(
|
|
1127
861
|
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1128
862
|
);
|
|
1129
|
-
|
|
863
|
+
const stableRef = useRef(null);
|
|
864
|
+
const previous = stableRef.current;
|
|
865
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
866
|
+
stableRef.current = stable;
|
|
867
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1130
868
|
}
|
|
1131
869
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1132
870
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1246,6 +984,13 @@ function useFrame$1(callback, priorityOrOptions) {
|
|
|
1246
984
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1247
985
|
*/
|
|
1248
986
|
scheduler: scheduler2,
|
|
987
|
+
/**
|
|
988
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
989
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
990
|
+
*/
|
|
991
|
+
get rootId() {
|
|
992
|
+
return getScheduler().getJobRootId(id);
|
|
993
|
+
},
|
|
1249
994
|
/**
|
|
1250
995
|
* Manually step this job only.
|
|
1251
996
|
* Bypasses FPS limiting - always runs.
|
|
@@ -1262,6 +1007,14 @@ function useFrame$1(callback, priorityOrOptions) {
|
|
|
1262
1007
|
stepAll: (timestamp) => {
|
|
1263
1008
|
getScheduler().step(timestamp);
|
|
1264
1009
|
},
|
|
1010
|
+
/**
|
|
1011
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1012
|
+
*/
|
|
1013
|
+
invalidate: (frames, stackFrames) => {
|
|
1014
|
+
const scheduler3 = getScheduler();
|
|
1015
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1016
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1017
|
+
},
|
|
1265
1018
|
/**
|
|
1266
1019
|
* Pause this job (set enabled=false).
|
|
1267
1020
|
* Job remains registered but won't run.
|
|
@@ -1291,6 +1044,11 @@ function getUrls(input) {
|
|
|
1291
1044
|
if (Array.isArray(input)) return input;
|
|
1292
1045
|
return Object.values(input);
|
|
1293
1046
|
}
|
|
1047
|
+
function inputSignature(input) {
|
|
1048
|
+
if (typeof input === "string") return input;
|
|
1049
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1050
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1051
|
+
}
|
|
1294
1052
|
function allUrlsCached(urls, textureCache) {
|
|
1295
1053
|
return urls.every((url) => textureCache.has(url));
|
|
1296
1054
|
}
|
|
@@ -1316,24 +1074,37 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1316
1074
|
const onLoadRef = useRef(onLoad);
|
|
1317
1075
|
onLoadRef.current = onLoad;
|
|
1318
1076
|
const onLoadCalledForRef = useRef(null);
|
|
1319
|
-
const
|
|
1077
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
1078
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
1079
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1320
1080
|
const cachedResult = useMemo(() => {
|
|
1321
1081
|
if (!cache) return null;
|
|
1322
1082
|
const textures = store.getState().textures;
|
|
1323
1083
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1324
|
-
return buildFromCache(
|
|
1325
|
-
}, [cache, urls,
|
|
1084
|
+
return buildFromCache(stableInput, textures);
|
|
1085
|
+
}, [cache, urls, stableInput, store]);
|
|
1326
1086
|
const loadedTextures = useLoader(
|
|
1327
1087
|
TextureLoader,
|
|
1328
|
-
IsObject(
|
|
1088
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1329
1089
|
);
|
|
1330
|
-
const
|
|
1090
|
+
const mappedTextures = useMemo(() => {
|
|
1091
|
+
if (cachedResult) return cachedResult;
|
|
1092
|
+
if (IsObject(stableInput)) {
|
|
1093
|
+
const keyed = {};
|
|
1094
|
+
const textureArray = loadedTextures;
|
|
1095
|
+
let i = 0;
|
|
1096
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1097
|
+
return keyed;
|
|
1098
|
+
} else {
|
|
1099
|
+
return loadedTextures;
|
|
1100
|
+
}
|
|
1101
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1331
1102
|
useLayoutEffect(() => {
|
|
1332
1103
|
if (cachedResult) return;
|
|
1333
1104
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
1334
1105
|
onLoadCalledForRef.current = inputKey;
|
|
1335
|
-
onLoadRef.current?.(
|
|
1336
|
-
}, [cachedResult,
|
|
1106
|
+
onLoadRef.current?.(mappedTextures);
|
|
1107
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
1337
1108
|
useEffect(() => {
|
|
1338
1109
|
if (cachedResult) return;
|
|
1339
1110
|
if ("initTexture" in renderer) {
|
|
@@ -1352,30 +1123,18 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1352
1123
|
});
|
|
1353
1124
|
}
|
|
1354
1125
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1355
|
-
const mappedTextures = useMemo(() => {
|
|
1356
|
-
if (cachedResult) return cachedResult;
|
|
1357
|
-
if (IsObject(input)) {
|
|
1358
|
-
const keyed = {};
|
|
1359
|
-
const textureArray = loadedTextures;
|
|
1360
|
-
let i = 0;
|
|
1361
|
-
for (const key in input) keyed[key] = textureArray[i++];
|
|
1362
|
-
return keyed;
|
|
1363
|
-
} else {
|
|
1364
|
-
return loadedTextures;
|
|
1365
|
-
}
|
|
1366
|
-
}, [input, loadedTextures, cachedResult]);
|
|
1367
1126
|
useEffect(() => {
|
|
1368
1127
|
if (!cache) return;
|
|
1369
1128
|
const urlTextureMap = [];
|
|
1370
|
-
if (typeof
|
|
1371
|
-
urlTextureMap.push([
|
|
1372
|
-
} else if (Array.isArray(
|
|
1129
|
+
if (typeof stableInput === "string") {
|
|
1130
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1131
|
+
} else if (Array.isArray(stableInput)) {
|
|
1373
1132
|
const textureArray = mappedTextures;
|
|
1374
|
-
|
|
1375
|
-
} else if (IsObject(
|
|
1133
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1134
|
+
} else if (IsObject(stableInput)) {
|
|
1376
1135
|
const textureRecord = mappedTextures;
|
|
1377
|
-
for (const key in
|
|
1378
|
-
const url =
|
|
1136
|
+
for (const key in stableInput) {
|
|
1137
|
+
const url = stableInput[key];
|
|
1379
1138
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1380
1139
|
}
|
|
1381
1140
|
}
|
|
@@ -1404,7 +1163,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1404
1163
|
}
|
|
1405
1164
|
return { _textureRefs: refs };
|
|
1406
1165
|
});
|
|
1407
|
-
}, [cache,
|
|
1166
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1408
1167
|
return mappedTextures;
|
|
1409
1168
|
}
|
|
1410
1169
|
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
@@ -1565,7 +1324,7 @@ function useEnvironment({
|
|
|
1565
1324
|
texture = texture.renderTarget?.texture;
|
|
1566
1325
|
}
|
|
1567
1326
|
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
1568
|
-
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
1327
|
+
texture.colorSpace = colorSpace ?? (isCubemap && extension !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
1569
1328
|
return texture;
|
|
1570
1329
|
}
|
|
1571
1330
|
const preloadDefaultOptions = {
|
|
@@ -1618,22 +1377,15 @@ function getExtension(files) {
|
|
|
1618
1377
|
const isCubemap = isArray(files) && files.length === 6;
|
|
1619
1378
|
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
1620
1379
|
const firstEntry = isArray(files) ? files[0] : files;
|
|
1621
|
-
const
|
|
1380
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1381
|
+
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;
|
|
1622
1382
|
return { extension, isCubemap, isGainmap };
|
|
1623
1383
|
}
|
|
1624
1384
|
function getLoader(extension) {
|
|
1625
|
-
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
1385
|
+
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr-cube" ? HDRCubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
1626
1386
|
return loader;
|
|
1627
1387
|
}
|
|
1628
1388
|
|
|
1629
|
-
function useStore() {
|
|
1630
|
-
const store = useContext(context);
|
|
1631
|
-
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1632
|
-
return store;
|
|
1633
|
-
}
|
|
1634
|
-
function useThree$1(selector = (state) => state, equalityFn) {
|
|
1635
|
-
return useStore()(selector, equalityFn);
|
|
1636
|
-
}
|
|
1637
1389
|
function useInstanceHandle(ref) {
|
|
1638
1390
|
const instance = useRef(null);
|
|
1639
1391
|
useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
@@ -1673,22 +1425,28 @@ function addTail(callback) {
|
|
|
1673
1425
|
return getScheduler().onIdle(callback);
|
|
1674
1426
|
}
|
|
1675
1427
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1676
|
-
|
|
1428
|
+
const rootId = state?.internal?.rootId;
|
|
1429
|
+
const scheduler = getScheduler();
|
|
1430
|
+
if (rootId) scheduler.invalidateRoot(rootId, frames, stackFrames);
|
|
1431
|
+
else scheduler.invalidate(frames, stackFrames);
|
|
1677
1432
|
}
|
|
1678
|
-
function advance(timestamp) {
|
|
1679
|
-
|
|
1433
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1434
|
+
const rootId = state?.internal?.rootId;
|
|
1435
|
+
const scheduler = getScheduler();
|
|
1436
|
+
if (rootId) scheduler.stepRoot(rootId, timestamp);
|
|
1437
|
+
else scheduler.step(timestamp);
|
|
1680
1438
|
}
|
|
1681
1439
|
|
|
1682
|
-
const version = "10.0.0-alpha.
|
|
1440
|
+
const version = "10.0.0-alpha.5";
|
|
1683
1441
|
const packageData = {
|
|
1684
1442
|
version: version};
|
|
1685
1443
|
|
|
1686
1444
|
function Xb(Tt) {
|
|
1687
1445
|
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
1688
1446
|
}
|
|
1689
|
-
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
1447
|
+
var Rm = { exports: {} }, Og = { exports: {} }, _b$1;
|
|
1690
1448
|
function Kb() {
|
|
1691
|
-
return _b || (_b = 1, (function(Tt) {
|
|
1449
|
+
return _b$1 || (_b$1 = 1, (function(Tt) {
|
|
1692
1450
|
Tt.exports = function(m) {
|
|
1693
1451
|
function Yn(t, r, a, l) {
|
|
1694
1452
|
return new uc(t, r, a, l);
|
|
@@ -13538,7 +13296,10 @@ function extend(objects) {
|
|
|
13538
13296
|
catalogue[Component] = objects;
|
|
13539
13297
|
return Component;
|
|
13540
13298
|
} else {
|
|
13541
|
-
|
|
13299
|
+
for (const name in objects) {
|
|
13300
|
+
const object = objects[name];
|
|
13301
|
+
if (isConstructor(object)) catalogue[name] = object;
|
|
13302
|
+
}
|
|
13542
13303
|
}
|
|
13543
13304
|
}
|
|
13544
13305
|
function validateInstance(type, props) {
|
|
@@ -13886,7 +13647,7 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13886
13647
|
getRootHostContext: () => NO_CONTEXT,
|
|
13887
13648
|
getChildHostContext: () => NO_CONTEXT,
|
|
13888
13649
|
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
13889
|
-
validateInstance(type, newProps);
|
|
13650
|
+
validateInstance(instance.type, newProps);
|
|
13890
13651
|
let reconstruct = false;
|
|
13891
13652
|
if (instance.type === "primitive" && oldProps.object !== newProps.object) reconstruct = true;
|
|
13892
13653
|
else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
|
|
@@ -13913,8 +13674,8 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13913
13674
|
for (const prop in instance.props) {
|
|
13914
13675
|
const value = instance.props[prop];
|
|
13915
13676
|
if (isFromRef(value)) {
|
|
13916
|
-
const ref = value
|
|
13917
|
-
if (ref.current != null) resolved[prop] = ref.current;
|
|
13677
|
+
const { [FROM_REF]: ref, transform } = value;
|
|
13678
|
+
if (ref.current != null) resolved[prop] = transform ? transform(ref.current) : ref.current;
|
|
13918
13679
|
}
|
|
13919
13680
|
}
|
|
13920
13681
|
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
@@ -14058,6 +13819,335 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14058
13819
|
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14059
13820
|
});
|
|
14060
13821
|
|
|
13822
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
13823
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
13824
|
+
if (!stack) return false;
|
|
13825
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
13826
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
13827
|
+
}
|
|
13828
|
+
|
|
13829
|
+
const createStore = (invalidate, advance) => {
|
|
13830
|
+
const rootStore = createWithEqualityFn((set, get) => {
|
|
13831
|
+
const position = new Vector3();
|
|
13832
|
+
const defaultTarget = new Vector3();
|
|
13833
|
+
const tempTarget = new Vector3();
|
|
13834
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
13835
|
+
const { width, height, top, left } = size;
|
|
13836
|
+
const aspect = width / height;
|
|
13837
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
13838
|
+
else tempTarget.set(...target);
|
|
13839
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
13840
|
+
if (isOrthographicCamera(camera)) {
|
|
13841
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
13842
|
+
} else {
|
|
13843
|
+
const fov = camera.fov * Math.PI / 180;
|
|
13844
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
13845
|
+
const w = h * (width / height);
|
|
13846
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
13847
|
+
}
|
|
13848
|
+
}
|
|
13849
|
+
let performanceTimeout = void 0;
|
|
13850
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
13851
|
+
const pointer = new Vector2();
|
|
13852
|
+
const rootState = {
|
|
13853
|
+
set,
|
|
13854
|
+
get,
|
|
13855
|
+
// Mock objects that have to be configured
|
|
13856
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
13857
|
+
primaryStore: null,
|
|
13858
|
+
gl: null,
|
|
13859
|
+
renderer: null,
|
|
13860
|
+
camera: null,
|
|
13861
|
+
frustum: new Frustum(),
|
|
13862
|
+
autoUpdateFrustum: true,
|
|
13863
|
+
raycaster: null,
|
|
13864
|
+
events: {
|
|
13865
|
+
priority: 1,
|
|
13866
|
+
enabled: true,
|
|
13867
|
+
connected: false,
|
|
13868
|
+
frameTimedRaycasts: true,
|
|
13869
|
+
alwaysFireOnScroll: true,
|
|
13870
|
+
updateOnFrame: false
|
|
13871
|
+
},
|
|
13872
|
+
scene: null,
|
|
13873
|
+
rootScene: null,
|
|
13874
|
+
xr: null,
|
|
13875
|
+
inspector: null,
|
|
13876
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
13877
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
13878
|
+
textureColorSpace: SRGBColorSpace,
|
|
13879
|
+
isLegacy: false,
|
|
13880
|
+
webGPUSupported: false,
|
|
13881
|
+
isNative: false,
|
|
13882
|
+
controls: null,
|
|
13883
|
+
pointer,
|
|
13884
|
+
mouse: pointer,
|
|
13885
|
+
frameloop: "always",
|
|
13886
|
+
onPointerMissed: void 0,
|
|
13887
|
+
onDragOverMissed: void 0,
|
|
13888
|
+
onDropMissed: void 0,
|
|
13889
|
+
performance: {
|
|
13890
|
+
current: 1,
|
|
13891
|
+
min: 0.5,
|
|
13892
|
+
max: 1,
|
|
13893
|
+
debounce: 200,
|
|
13894
|
+
regress: () => {
|
|
13895
|
+
const state2 = get();
|
|
13896
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
13897
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
13898
|
+
performanceTimeout = setTimeout(
|
|
13899
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
13900
|
+
state2.performance.debounce
|
|
13901
|
+
);
|
|
13902
|
+
}
|
|
13903
|
+
},
|
|
13904
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
13905
|
+
viewport: {
|
|
13906
|
+
initialDpr: 0,
|
|
13907
|
+
dpr: 0,
|
|
13908
|
+
width: 0,
|
|
13909
|
+
height: 0,
|
|
13910
|
+
top: 0,
|
|
13911
|
+
left: 0,
|
|
13912
|
+
aspect: 0,
|
|
13913
|
+
distance: 0,
|
|
13914
|
+
factor: 0,
|
|
13915
|
+
getCurrentViewport
|
|
13916
|
+
},
|
|
13917
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
13918
|
+
setSize: (width, height, top, left) => {
|
|
13919
|
+
const state2 = get();
|
|
13920
|
+
if (width === void 0) {
|
|
13921
|
+
set({ _sizeImperative: false });
|
|
13922
|
+
if (state2._sizeProps) {
|
|
13923
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
13924
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
13925
|
+
const currentSize = state2.size;
|
|
13926
|
+
const newSize = {
|
|
13927
|
+
width: propW ?? currentSize.width,
|
|
13928
|
+
height: propH ?? currentSize.height,
|
|
13929
|
+
top: currentSize.top,
|
|
13930
|
+
left: currentSize.left
|
|
13931
|
+
};
|
|
13932
|
+
set((s) => ({
|
|
13933
|
+
size: newSize,
|
|
13934
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
13935
|
+
}));
|
|
13936
|
+
get().invalidate();
|
|
13937
|
+
}
|
|
13938
|
+
}
|
|
13939
|
+
return;
|
|
13940
|
+
}
|
|
13941
|
+
const w = width;
|
|
13942
|
+
const h = height ?? width;
|
|
13943
|
+
const t = top ?? state2.size.top;
|
|
13944
|
+
const l = left ?? state2.size.left;
|
|
13945
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
13946
|
+
set((s) => ({
|
|
13947
|
+
size,
|
|
13948
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
13949
|
+
_sizeImperative: true
|
|
13950
|
+
}));
|
|
13951
|
+
get().invalidate();
|
|
13952
|
+
},
|
|
13953
|
+
setDpr: (dpr) => set((state2) => {
|
|
13954
|
+
const resolved = calculateDpr(dpr);
|
|
13955
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
13956
|
+
}),
|
|
13957
|
+
setFrameloop: (frameloop = "always") => {
|
|
13958
|
+
const rootId = get().internal.rootId;
|
|
13959
|
+
if (rootId) getScheduler().setRootFrameloop(rootId, frameloop);
|
|
13960
|
+
set(() => ({ frameloop }));
|
|
13961
|
+
},
|
|
13962
|
+
setError: (error) => set(() => ({ error })),
|
|
13963
|
+
error: null,
|
|
13964
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
13965
|
+
uniforms: {},
|
|
13966
|
+
nodes: {},
|
|
13967
|
+
buffers: {},
|
|
13968
|
+
gpuStorage: {},
|
|
13969
|
+
textures: /* @__PURE__ */ new Map(),
|
|
13970
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
13971
|
+
renderPipeline: null,
|
|
13972
|
+
passes: {},
|
|
13973
|
+
_hmrVersion: 0,
|
|
13974
|
+
_sizeImperative: false,
|
|
13975
|
+
_sizeProps: null,
|
|
13976
|
+
previousRoot: void 0,
|
|
13977
|
+
internal: {
|
|
13978
|
+
// Events
|
|
13979
|
+
interaction: [],
|
|
13980
|
+
subscribers: [],
|
|
13981
|
+
// Per-pointer state (new unified structure)
|
|
13982
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
13983
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
13984
|
+
lastEvent: React.createRef(),
|
|
13985
|
+
// Deprecated but kept for backwards compatibility
|
|
13986
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
13987
|
+
initialClick: [0, 0],
|
|
13988
|
+
initialHits: [],
|
|
13989
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
13990
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
13991
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
13992
|
+
// Occlusion system (WebGPU only)
|
|
13993
|
+
occlusionEnabled: false,
|
|
13994
|
+
occlusionObserver: null,
|
|
13995
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
13996
|
+
helperGroup: null,
|
|
13997
|
+
// Updates
|
|
13998
|
+
active: false,
|
|
13999
|
+
frames: 0,
|
|
14000
|
+
priority: 0,
|
|
14001
|
+
subscribe: (ref, priority, store) => {
|
|
14002
|
+
const internal = get().internal;
|
|
14003
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
14004
|
+
internal.subscribers.push({ ref, priority, store });
|
|
14005
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14006
|
+
return () => {
|
|
14007
|
+
const internal2 = get().internal;
|
|
14008
|
+
if (internal2?.subscribers) {
|
|
14009
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14010
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14011
|
+
}
|
|
14012
|
+
};
|
|
14013
|
+
},
|
|
14014
|
+
// Renderer Storage (single source of truth)
|
|
14015
|
+
actualRenderer: null,
|
|
14016
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14017
|
+
scheduler: null,
|
|
14018
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
14019
|
+
renderOverride: null
|
|
14020
|
+
}
|
|
14021
|
+
};
|
|
14022
|
+
return rootState;
|
|
14023
|
+
});
|
|
14024
|
+
const state = rootStore.getState();
|
|
14025
|
+
Object.defineProperty(state, "gl", {
|
|
14026
|
+
get() {
|
|
14027
|
+
const currentState = rootStore.getState();
|
|
14028
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14029
|
+
const stack = new Error().stack || "";
|
|
14030
|
+
if (!isInternalRendererAccess(stack)) {
|
|
14031
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14032
|
+
notifyDepreciated({
|
|
14033
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
14034
|
+
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
|
|
14035
|
+
});
|
|
14036
|
+
}
|
|
14037
|
+
}
|
|
14038
|
+
return currentState.internal.actualRenderer;
|
|
14039
|
+
},
|
|
14040
|
+
set(value) {
|
|
14041
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14042
|
+
},
|
|
14043
|
+
enumerable: true,
|
|
14044
|
+
configurable: true
|
|
14045
|
+
});
|
|
14046
|
+
Object.defineProperty(state, "renderer", {
|
|
14047
|
+
get() {
|
|
14048
|
+
return rootStore.getState().internal.actualRenderer;
|
|
14049
|
+
},
|
|
14050
|
+
set(value) {
|
|
14051
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14052
|
+
},
|
|
14053
|
+
enumerable: true,
|
|
14054
|
+
configurable: true
|
|
14055
|
+
});
|
|
14056
|
+
let oldScene = state.scene;
|
|
14057
|
+
rootStore.subscribe(() => {
|
|
14058
|
+
const currentState = rootStore.getState();
|
|
14059
|
+
const { scene, rootScene, set } = currentState;
|
|
14060
|
+
if (scene !== oldScene) {
|
|
14061
|
+
oldScene = scene;
|
|
14062
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
14063
|
+
set({ rootScene: scene });
|
|
14064
|
+
}
|
|
14065
|
+
}
|
|
14066
|
+
});
|
|
14067
|
+
let oldSize = state.size;
|
|
14068
|
+
let oldDpr = state.viewport.dpr;
|
|
14069
|
+
let oldCamera = state.camera;
|
|
14070
|
+
rootStore.subscribe(() => {
|
|
14071
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14072
|
+
const actualRenderer = internal.actualRenderer;
|
|
14073
|
+
const canvasTarget = internal.canvasTarget;
|
|
14074
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14075
|
+
oldSize = size;
|
|
14076
|
+
oldDpr = viewport.dpr;
|
|
14077
|
+
updateCamera(camera, size);
|
|
14078
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14079
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14080
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
14081
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14082
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
14083
|
+
}
|
|
14084
|
+
if (camera !== oldCamera) {
|
|
14085
|
+
oldCamera = camera;
|
|
14086
|
+
const { rootScene } = rootStore.getState();
|
|
14087
|
+
if (camera && rootScene && !camera.parent) {
|
|
14088
|
+
rootScene.add(camera);
|
|
14089
|
+
}
|
|
14090
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14091
|
+
const currentState = rootStore.getState();
|
|
14092
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
14093
|
+
updateFrustum(camera, currentState.frustum);
|
|
14094
|
+
}
|
|
14095
|
+
}
|
|
14096
|
+
});
|
|
14097
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
14098
|
+
return rootStore;
|
|
14099
|
+
};
|
|
14100
|
+
|
|
14101
|
+
const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
|
|
14102
|
+
function getRegistry() {
|
|
14103
|
+
return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
|
|
14104
|
+
extensions: /* @__PURE__ */ new Map(),
|
|
14105
|
+
roots: /* @__PURE__ */ new Set(),
|
|
14106
|
+
applied: /* @__PURE__ */ new WeakMap()
|
|
14107
|
+
});
|
|
14108
|
+
}
|
|
14109
|
+
function setupRoot(registry, store, extension) {
|
|
14110
|
+
let applied = registry.applied.get(store);
|
|
14111
|
+
if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
|
|
14112
|
+
if (applied.has(extension.name)) return;
|
|
14113
|
+
applied.set(extension.name, extension);
|
|
14114
|
+
const patch = extension.setup?.(store);
|
|
14115
|
+
if (patch) store.setState(patch);
|
|
14116
|
+
}
|
|
14117
|
+
function registerRootExtension(extension) {
|
|
14118
|
+
const registry = getRegistry();
|
|
14119
|
+
registry.extensions.set(extension.name, extension);
|
|
14120
|
+
for (const store of registry.roots) setupRoot(registry, store, extension);
|
|
14121
|
+
return () => {
|
|
14122
|
+
if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
|
|
14123
|
+
};
|
|
14124
|
+
}
|
|
14125
|
+
function setRenderOverride(store, render) {
|
|
14126
|
+
store.getState().internal.renderOverride = render;
|
|
14127
|
+
}
|
|
14128
|
+
function attachRootExtensions(store) {
|
|
14129
|
+
const registry = getRegistry();
|
|
14130
|
+
registry.roots.add(store);
|
|
14131
|
+
for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
|
|
14132
|
+
}
|
|
14133
|
+
function current(registry, setUpBy) {
|
|
14134
|
+
return registry.extensions.get(setUpBy.name) ?? setUpBy;
|
|
14135
|
+
}
|
|
14136
|
+
function detachRootExtensions(store) {
|
|
14137
|
+
const registry = getRegistry();
|
|
14138
|
+
if (!registry.roots.delete(store)) return;
|
|
14139
|
+
const applied = registry.applied.get(store);
|
|
14140
|
+
registry.applied.delete(store);
|
|
14141
|
+
if (!applied) return;
|
|
14142
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
|
|
14143
|
+
}
|
|
14144
|
+
function notifyRootExtensionsHmr(store) {
|
|
14145
|
+
const registry = getRegistry();
|
|
14146
|
+
const applied = registry.applied.get(store);
|
|
14147
|
+
if (!applied) return;
|
|
14148
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
|
|
14149
|
+
}
|
|
14150
|
+
|
|
14061
14151
|
const isRenderer = (def) => !!def?.render;
|
|
14062
14152
|
const _roots = /* @__PURE__ */ new Map();
|
|
14063
14153
|
const shallowLoose = { objects: "shallow", strict: false };
|
|
@@ -14195,9 +14285,8 @@ function createRoot(canvas) {
|
|
|
14195
14285
|
if (!renderer.hasInitialized?.()) {
|
|
14196
14286
|
const size2 = computeInitialSize(canvas, propsSize);
|
|
14197
14287
|
if (size2.width > 0 && size2.height > 0) {
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
canvas.height = size2.height * pixelRatio;
|
|
14288
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14289
|
+
renderer.setSize(size2.width, size2.height, false);
|
|
14201
14290
|
}
|
|
14202
14291
|
await renderer.init();
|
|
14203
14292
|
}
|
|
@@ -14206,7 +14295,7 @@ function createRoot(canvas) {
|
|
|
14206
14295
|
state.internal.actualRenderer = renderer;
|
|
14207
14296
|
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14208
14297
|
if (canvasId && !state.internal.isSecondary) {
|
|
14209
|
-
const canvasTarget =
|
|
14298
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14210
14299
|
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14211
14300
|
state.set((prev) => ({
|
|
14212
14301
|
internal: {
|
|
@@ -14320,7 +14409,7 @@ function createRoot(canvas) {
|
|
|
14320
14409
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14321
14410
|
const state2 = store.getState();
|
|
14322
14411
|
if (state2.frameloop === "never") return;
|
|
14323
|
-
advance(timestamp);
|
|
14412
|
+
advance(timestamp, true, state2);
|
|
14324
14413
|
};
|
|
14325
14414
|
const actualRenderer = state.internal.actualRenderer;
|
|
14326
14415
|
const handleSessionChange = () => {
|
|
@@ -14328,7 +14417,7 @@ function createRoot(canvas) {
|
|
|
14328
14417
|
const renderer2 = state2.internal.actualRenderer;
|
|
14329
14418
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14330
14419
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14331
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14420
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14332
14421
|
};
|
|
14333
14422
|
const xr = {
|
|
14334
14423
|
connect() {
|
|
@@ -14410,14 +14499,23 @@ function createRoot(canvas) {
|
|
|
14410
14499
|
const newRootId = canvasId || scheduler.generateRootId();
|
|
14411
14500
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14412
14501
|
getState: () => store.getState(),
|
|
14413
|
-
onError: (err) => store.getState().setError(err)
|
|
14502
|
+
onError: (err) => store.getState().setError(err),
|
|
14503
|
+
frameloop: store.getState().frameloop,
|
|
14504
|
+
before: schedulerConfig?.before,
|
|
14505
|
+
after: schedulerConfig?.after,
|
|
14506
|
+
order: schedulerConfig?.order
|
|
14414
14507
|
});
|
|
14415
14508
|
const unregisterCanvasTarget = scheduler.register(
|
|
14416
14509
|
() => {
|
|
14417
14510
|
const state2 = store.getState();
|
|
14418
|
-
|
|
14511
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14512
|
+
if (canvasTarget) {
|
|
14419
14513
|
const renderer2 = state2.internal.actualRenderer;
|
|
14420
|
-
renderer2.setCanvasTarget(
|
|
14514
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14515
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14516
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14517
|
+
renderer2.backend?.updateSize?.();
|
|
14518
|
+
}
|
|
14421
14519
|
}
|
|
14422
14520
|
},
|
|
14423
14521
|
{
|
|
@@ -14473,7 +14571,8 @@ function createRoot(canvas) {
|
|
|
14473
14571
|
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
14474
14572
|
if (userHandlesRender || state2.internal.priority) return;
|
|
14475
14573
|
try {
|
|
14476
|
-
|
|
14574
|
+
const renderOverride = state2.internal.renderOverride;
|
|
14575
|
+
if (renderOverride) renderOverride();
|
|
14477
14576
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
14478
14577
|
} catch (error) {
|
|
14479
14578
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -14486,8 +14585,7 @@ function createRoot(canvas) {
|
|
|
14486
14585
|
phase: "render",
|
|
14487
14586
|
system: true,
|
|
14488
14587
|
// Internal flag: this is a system job, not user-controlled
|
|
14489
|
-
//
|
|
14490
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14588
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14491
14589
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14492
14590
|
}
|
|
14493
14591
|
);
|
|
@@ -14506,8 +14604,22 @@ function createRoot(canvas) {
|
|
|
14506
14604
|
scheduler
|
|
14507
14605
|
}
|
|
14508
14606
|
}));
|
|
14607
|
+
} else {
|
|
14608
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14609
|
+
if (constraintsChanged) {
|
|
14610
|
+
scheduler.setRootConstraints(rootId, {
|
|
14611
|
+
before: schedulerConfig?.before,
|
|
14612
|
+
after: schedulerConfig?.after
|
|
14613
|
+
});
|
|
14614
|
+
}
|
|
14615
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14616
|
+
scheduler.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14617
|
+
}
|
|
14509
14618
|
}
|
|
14510
|
-
|
|
14619
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14620
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14621
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14622
|
+
attachRootExtensions(store);
|
|
14511
14623
|
onCreated = onCreatedCallback;
|
|
14512
14624
|
configured = true;
|
|
14513
14625
|
resolve();
|
|
@@ -14549,18 +14661,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14549
14661
|
const fiber = root?.fiber;
|
|
14550
14662
|
if (fiber) {
|
|
14551
14663
|
const state = root?.store.getState();
|
|
14552
|
-
if (state)
|
|
14664
|
+
if (state) {
|
|
14665
|
+
state.internal.active = false;
|
|
14666
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14667
|
+
if (unregisterRoot) {
|
|
14668
|
+
unregisterRoot();
|
|
14669
|
+
state.internal.unregisterRoot = void 0;
|
|
14670
|
+
}
|
|
14671
|
+
}
|
|
14553
14672
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14673
|
+
if (root?.store) detachRootExtensions(root.store);
|
|
14554
14674
|
if (state) {
|
|
14555
14675
|
setTimeout(() => {
|
|
14556
14676
|
try {
|
|
14557
14677
|
const renderer = state.internal.actualRenderer;
|
|
14558
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14559
|
-
if (unregisterRoot) unregisterRoot();
|
|
14560
14678
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14561
14679
|
if (unregisterPrimary) unregisterPrimary();
|
|
14562
14680
|
const canvasTarget = state.internal.canvasTarget;
|
|
14563
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14681
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14564
14682
|
state.events.disconnect?.();
|
|
14565
14683
|
cleanupHelperGroup(root.store);
|
|
14566
14684
|
if (state.isLegacy && renderer) {
|
|
@@ -14630,11 +14748,24 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14630
14748
|
}
|
|
14631
14749
|
};
|
|
14632
14750
|
}, [portalScene, container, injectScene]);
|
|
14751
|
+
const lastRootState = useRef(null);
|
|
14633
14752
|
const inject = useMutableCallback((rootState, injectState) => {
|
|
14753
|
+
const followed = {};
|
|
14754
|
+
const lastRoot = lastRootState.current;
|
|
14755
|
+
if (lastRoot) {
|
|
14756
|
+
for (const key in rootState) {
|
|
14757
|
+
const field = key;
|
|
14758
|
+
const changed = rootState[field] !== lastRoot[field];
|
|
14759
|
+
const inherited = !(key in rest) && injectState[field] === lastRoot[field];
|
|
14760
|
+
if (changed && inherited) followed[field] = rootState[field];
|
|
14761
|
+
}
|
|
14762
|
+
}
|
|
14763
|
+
lastRootState.current = rootState;
|
|
14634
14764
|
const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
|
|
14635
14765
|
let viewport = void 0;
|
|
14636
|
-
|
|
14637
|
-
|
|
14766
|
+
const portalCamera = followed.camera ?? injectState.camera;
|
|
14767
|
+
if (portalCamera && (size || injectState.size)) {
|
|
14768
|
+
const camera = portalCamera;
|
|
14638
14769
|
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), resolvedSize);
|
|
14639
14770
|
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14640
14771
|
}
|
|
@@ -14643,6 +14774,7 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14643
14774
|
// The intersect consists of the previous root state
|
|
14644
14775
|
...rootState,
|
|
14645
14776
|
...injectState,
|
|
14777
|
+
...followed,
|
|
14646
14778
|
// Portals have their own scene - always a real THREE.Scene (injected if needed)
|
|
14647
14779
|
scene: portalScene,
|
|
14648
14780
|
// rootScene always points to the actual THREE.Scene, even inside portals
|
|
@@ -14701,16 +14833,11 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14701
14833
|
const oldbg = target.background;
|
|
14702
14834
|
const oldenv = target.environment;
|
|
14703
14835
|
const oldSceneProps = {
|
|
14704
|
-
// @ts-ignore
|
|
14705
14836
|
backgroundBlurriness: target.backgroundBlurriness,
|
|
14706
|
-
// @ts-ignore
|
|
14707
14837
|
backgroundIntensity: target.backgroundIntensity,
|
|
14708
|
-
|
|
14709
|
-
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
14710
|
-
// @ts-ignore
|
|
14838
|
+
backgroundRotation: target.backgroundRotation.clone(),
|
|
14711
14839
|
environmentIntensity: target.environmentIntensity,
|
|
14712
|
-
|
|
14713
|
-
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
14840
|
+
environmentRotation: target.environmentRotation.clone()
|
|
14714
14841
|
};
|
|
14715
14842
|
if (background !== "only") target.environment = texture;
|
|
14716
14843
|
if (background) target.background = texture;
|
|
@@ -14915,153 +15042,24 @@ function parseBackground(background) {
|
|
|
14915
15042
|
return { files: background, background: true };
|
|
14916
15043
|
}
|
|
14917
15044
|
return { color: background, background: true };
|
|
14918
|
-
}
|
|
14919
|
-
if (background.isColor) {
|
|
14920
|
-
return { color: background, background: true };
|
|
14921
|
-
}
|
|
14922
|
-
return null;
|
|
14923
|
-
}
|
|
14924
|
-
|
|
14925
|
-
function parseRendererConfig(rendererProp) {
|
|
14926
|
-
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
14927
|
-
if (isRendererConfig) {
|
|
14928
|
-
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
14929
|
-
return {
|
|
14930
|
-
primaryCanvas: pc,
|
|
14931
|
-
scheduler: sc,
|
|
14932
|
-
renderer: Object.keys(rest).length > 0 ? rest : rendererProp
|
|
14933
|
-
};
|
|
14934
|
-
}
|
|
14935
|
-
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
14936
|
-
}
|
|
14937
|
-
|
|
14938
|
-
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
14939
|
-
const ROOT_SCOPE = "";
|
|
14940
|
-
const registries = /* @__PURE__ */ new WeakMap();
|
|
14941
|
-
function getKindRegistry(store, kind) {
|
|
14942
|
-
let registry = registries.get(store);
|
|
14943
|
-
if (!registry) {
|
|
14944
|
-
registry = {
|
|
14945
|
-
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14946
|
-
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14947
|
-
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14948
|
-
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
14949
|
-
};
|
|
14950
|
-
registries.set(store, registry);
|
|
14951
|
-
}
|
|
14952
|
-
return registry[kind];
|
|
14953
|
-
}
|
|
14954
|
-
function resolvePrimary$1(store) {
|
|
14955
|
-
return store.getState().primaryStore ?? store;
|
|
14956
|
-
}
|
|
14957
|
-
function isScopeValid(store, kind, scopeKey) {
|
|
14958
|
-
return getKindRegistry(store, kind).valid.has(scopeKey);
|
|
14959
|
-
}
|
|
14960
|
-
function peekStaged(store, kind, scopeKey) {
|
|
14961
|
-
return getKindRegistry(store, kind).staged.get(scopeKey);
|
|
14962
|
-
}
|
|
14963
|
-
function stageEntries(store, kind, scopeKey, entries) {
|
|
14964
|
-
const { staged } = getKindRegistry(store, kind);
|
|
14965
|
-
const current = staged.get(scopeKey);
|
|
14966
|
-
if (current) Object.assign(current, entries);
|
|
14967
|
-
else staged.set(scopeKey, { ...entries });
|
|
14968
|
-
}
|
|
14969
|
-
function readCommittedScope(map, scopeKey, isLeaf) {
|
|
14970
|
-
if (scopeKey === ROOT_SCOPE) {
|
|
14971
|
-
const leaves = {};
|
|
14972
|
-
for (const [key, value] of Object.entries(map)) if (isLeaf(value)) leaves[key] = value;
|
|
14973
|
-
return leaves;
|
|
14974
|
-
}
|
|
14975
|
-
const scopeData = map[scopeKey];
|
|
14976
|
-
if (scopeData && typeof scopeData === "object" && !isLeaf(scopeData)) return scopeData;
|
|
14977
|
-
return {};
|
|
14978
|
-
}
|
|
14979
|
-
function withStagedOverlay(store, kind, committed) {
|
|
14980
|
-
const { staged } = getKindRegistry(store, kind);
|
|
14981
|
-
if (staged.size === 0) return committed;
|
|
14982
|
-
const view = { ...committed };
|
|
14983
|
-
for (const [scopeKey, entries] of staged) {
|
|
14984
|
-
if (scopeKey === ROOT_SCOPE) Object.assign(view, entries);
|
|
14985
|
-
else view[scopeKey] = { ...view[scopeKey], ...entries };
|
|
14986
|
-
}
|
|
14987
|
-
return view;
|
|
14988
|
-
}
|
|
14989
|
-
function flushStagedScope(store, kind, scopeKey, isLeaf) {
|
|
14990
|
-
const registry = getKindRegistry(store, kind);
|
|
14991
|
-
const staged = registry.staged.get(scopeKey);
|
|
14992
|
-
if (!staged) return;
|
|
14993
|
-
registry.staged.delete(scopeKey);
|
|
14994
|
-
const replace = !registry.valid.has(scopeKey);
|
|
14995
|
-
store.setState((state) => {
|
|
14996
|
-
const map = state[kind];
|
|
14997
|
-
if (scopeKey === ROOT_SCOPE) {
|
|
14998
|
-
if (!replace) return { [kind]: { ...map, ...staged } };
|
|
14999
|
-
const next = {};
|
|
15000
|
-
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15001
|
-
return { [kind]: { ...next, ...staged } };
|
|
15002
|
-
}
|
|
15003
|
-
const current = replace ? {} : map[scopeKey] ?? {};
|
|
15004
|
-
return { [kind]: { ...map, [scopeKey]: { ...current, ...staged } } };
|
|
15005
|
-
});
|
|
15006
|
-
registry.valid.add(scopeKey);
|
|
15007
|
-
}
|
|
15008
|
-
function invalidateResource(store, kind, scopeKey) {
|
|
15009
|
-
const registry = getKindRegistry(store, kind);
|
|
15010
|
-
if (scopeKey === void 0) {
|
|
15011
|
-
registry.valid.clear();
|
|
15012
|
-
registry.staged.clear();
|
|
15013
|
-
} else {
|
|
15014
|
-
registry.valid.delete(scopeKey);
|
|
15015
|
-
registry.staged.delete(scopeKey);
|
|
15016
|
-
}
|
|
15017
|
-
}
|
|
15018
|
-
function rebuildResource(store, kind, userScope) {
|
|
15019
|
-
const primary = resolvePrimary$1(store);
|
|
15020
|
-
invalidateResource(primary, kind, userScope === "root" ? ROOT_SCOPE : userScope);
|
|
15021
|
-
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
15022
|
-
}
|
|
15023
|
-
function invalidateAllResources(store) {
|
|
15024
|
-
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
15025
|
-
}
|
|
15026
|
-
function removeResourceEntries(store, kind, names, scope, isLeaf) {
|
|
15027
|
-
const staged = peekStaged(store, kind, scope ?? ROOT_SCOPE);
|
|
15028
|
-
if (staged) for (const name of names) delete staged[name];
|
|
15029
|
-
store.setState((state) => {
|
|
15030
|
-
const map = state[kind];
|
|
15031
|
-
if (scope) {
|
|
15032
|
-
const currentScope = { ...map[scope] };
|
|
15033
|
-
for (const name of names) delete currentScope[name];
|
|
15034
|
-
return { [kind]: { ...map, [scope]: currentScope } };
|
|
15035
|
-
}
|
|
15036
|
-
const next = { ...map };
|
|
15037
|
-
for (const name of names) if (isLeaf(next[name])) delete next[name];
|
|
15038
|
-
return { [kind]: next };
|
|
15039
|
-
});
|
|
15040
|
-
}
|
|
15041
|
-
function clearResourceEntries(store, kind, scope, isLeaf) {
|
|
15042
|
-
const registry = getKindRegistry(store, kind);
|
|
15043
|
-
if (scope && scope !== "root") registry.staged.delete(scope);
|
|
15044
|
-
else if (scope === "root") registry.staged.delete(ROOT_SCOPE);
|
|
15045
|
-
else registry.staged.clear();
|
|
15046
|
-
store.setState((state) => {
|
|
15047
|
-
const map = state[kind];
|
|
15048
|
-
if (scope && scope !== "root") {
|
|
15049
|
-
const { [scope]: _, ...rest } = map;
|
|
15050
|
-
return { [kind]: rest };
|
|
15051
|
-
}
|
|
15052
|
-
if (scope === "root") {
|
|
15053
|
-
const next = {};
|
|
15054
|
-
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15055
|
-
return { [kind]: next };
|
|
15056
|
-
}
|
|
15057
|
-
return { [kind]: {} };
|
|
15058
|
-
});
|
|
15045
|
+
}
|
|
15046
|
+
if (background.isColor) {
|
|
15047
|
+
return { color: background, background: true };
|
|
15048
|
+
}
|
|
15049
|
+
return null;
|
|
15059
15050
|
}
|
|
15060
15051
|
|
|
15061
|
-
function
|
|
15062
|
-
const
|
|
15063
|
-
|
|
15064
|
-
|
|
15052
|
+
function parseRendererConfig(rendererProp) {
|
|
15053
|
+
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
15054
|
+
if (isRendererConfig) {
|
|
15055
|
+
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
15056
|
+
return {
|
|
15057
|
+
primaryCanvas: pc,
|
|
15058
|
+
scheduler: sc,
|
|
15059
|
+
renderer: Object.keys(rest).length > 0 ? rest : rendererProp
|
|
15060
|
+
};
|
|
15061
|
+
}
|
|
15062
|
+
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
15065
15063
|
}
|
|
15066
15064
|
|
|
15067
15065
|
function CanvasImpl({
|
|
@@ -15101,9 +15099,9 @@ function CanvasImpl({
|
|
|
15101
15099
|
React.useMemo(() => extend(THREE), []);
|
|
15102
15100
|
const Bridge = useBridge();
|
|
15103
15101
|
const backgroundProps = React.useMemo(() => parseBackground(background), [background]);
|
|
15104
|
-
const
|
|
15102
|
+
const [hasInitialSize, setHasInitialSize] = React.useState(false);
|
|
15105
15103
|
const measureConfig = React.useMemo(() => {
|
|
15106
|
-
if (!
|
|
15104
|
+
if (!hasInitialSize) {
|
|
15107
15105
|
return {
|
|
15108
15106
|
...resize,
|
|
15109
15107
|
scroll: resize?.scroll ?? true,
|
|
@@ -15115,7 +15113,7 @@ function CanvasImpl({
|
|
|
15115
15113
|
debounce: { scroll: 50, resize: 0 },
|
|
15116
15114
|
...resize
|
|
15117
15115
|
};
|
|
15118
|
-
}, [
|
|
15116
|
+
}, [hasInitialSize, resize]);
|
|
15119
15117
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
15120
15118
|
const effectiveSize = React.useMemo(() => {
|
|
15121
15119
|
let w = width ?? containerRect.width;
|
|
@@ -15131,9 +15129,7 @@ function CanvasImpl({
|
|
|
15131
15129
|
left: containerRect.left
|
|
15132
15130
|
};
|
|
15133
15131
|
}, [width, height, containerRect, forceEven]);
|
|
15134
|
-
if (!
|
|
15135
|
-
hasInitialSizeRef.current = true;
|
|
15136
|
-
}
|
|
15132
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15137
15133
|
const canvasRef = React.useRef(null);
|
|
15138
15134
|
const divRef = React.useRef(null);
|
|
15139
15135
|
React.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15247,6 +15243,7 @@ function CanvasImpl({
|
|
|
15247
15243
|
const canvas = canvasRef.current;
|
|
15248
15244
|
if (canvas) {
|
|
15249
15245
|
return () => {
|
|
15246
|
+
if (canvas.isConnected) return;
|
|
15250
15247
|
unmountComponentAtNode(canvas);
|
|
15251
15248
|
root.current = null;
|
|
15252
15249
|
};
|
|
@@ -15259,7 +15256,7 @@ function CanvasImpl({
|
|
|
15259
15256
|
const handleHMR = () => {
|
|
15260
15257
|
queueMicrotask(() => {
|
|
15261
15258
|
const rootEntry = _roots.get(canvas);
|
|
15262
|
-
if (rootEntry?.store)
|
|
15259
|
+
if (rootEntry?.store) notifyRootExtensionsHmr(rootEntry.store);
|
|
15263
15260
|
});
|
|
15264
15261
|
};
|
|
15265
15262
|
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
@@ -15305,20 +15302,159 @@ function CanvasImpl({
|
|
|
15305
15302
|
}
|
|
15306
15303
|
);
|
|
15307
15304
|
}
|
|
15308
|
-
function Canvas(props) {
|
|
15305
|
+
function Canvas$1(props) {
|
|
15309
15306
|
return /* @__PURE__ */ jsx(FiberProvider, { children: /* @__PURE__ */ jsx(CanvasImpl, { ...props }) });
|
|
15310
15307
|
}
|
|
15311
15308
|
|
|
15309
|
+
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
15310
|
+
const ROOT_SCOPE = "";
|
|
15311
|
+
const registries = /* @__PURE__ */ new WeakMap();
|
|
15312
|
+
function getKindRegistry(store, kind) {
|
|
15313
|
+
let registry = registries.get(store);
|
|
15314
|
+
if (!registry) {
|
|
15315
|
+
registry = {
|
|
15316
|
+
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
15317
|
+
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
15318
|
+
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
15319
|
+
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
15320
|
+
};
|
|
15321
|
+
registries.set(store, registry);
|
|
15322
|
+
}
|
|
15323
|
+
return registry[kind];
|
|
15324
|
+
}
|
|
15325
|
+
function resolvePrimary$1(store) {
|
|
15326
|
+
return store.getState().primaryStore ?? store;
|
|
15327
|
+
}
|
|
15328
|
+
function isScopeValid(store, kind, scopeKey) {
|
|
15329
|
+
return getKindRegistry(store, kind).valid.has(scopeKey);
|
|
15330
|
+
}
|
|
15331
|
+
function peekStaged(store, kind, scopeKey) {
|
|
15332
|
+
return getKindRegistry(store, kind).staged.get(scopeKey);
|
|
15333
|
+
}
|
|
15334
|
+
function stageEntries(store, kind, scopeKey, entries) {
|
|
15335
|
+
const { staged } = getKindRegistry(store, kind);
|
|
15336
|
+
const current = staged.get(scopeKey);
|
|
15337
|
+
if (current) Object.assign(current, entries);
|
|
15338
|
+
else staged.set(scopeKey, { ...entries });
|
|
15339
|
+
}
|
|
15340
|
+
function readCommittedScope(map, scopeKey, isLeaf) {
|
|
15341
|
+
if (scopeKey === ROOT_SCOPE) {
|
|
15342
|
+
const leaves = {};
|
|
15343
|
+
for (const [key, value] of Object.entries(map)) if (isLeaf(value)) leaves[key] = value;
|
|
15344
|
+
return leaves;
|
|
15345
|
+
}
|
|
15346
|
+
const scopeData = map[scopeKey];
|
|
15347
|
+
if (scopeData && typeof scopeData === "object" && !isLeaf(scopeData)) return scopeData;
|
|
15348
|
+
return {};
|
|
15349
|
+
}
|
|
15350
|
+
function withStagedOverlay(store, kind, committed) {
|
|
15351
|
+
const { staged } = getKindRegistry(store, kind);
|
|
15352
|
+
if (staged.size === 0) return committed;
|
|
15353
|
+
const view = { ...committed };
|
|
15354
|
+
for (const [scopeKey, entries] of staged) {
|
|
15355
|
+
if (scopeKey === ROOT_SCOPE) Object.assign(view, entries);
|
|
15356
|
+
else view[scopeKey] = { ...view[scopeKey], ...entries };
|
|
15357
|
+
}
|
|
15358
|
+
return view;
|
|
15359
|
+
}
|
|
15360
|
+
function flushStagedScope(store, kind, scopeKey, isLeaf) {
|
|
15361
|
+
const registry = getKindRegistry(store, kind);
|
|
15362
|
+
const staged = registry.staged.get(scopeKey);
|
|
15363
|
+
if (!staged) return;
|
|
15364
|
+
registry.staged.delete(scopeKey);
|
|
15365
|
+
const replace = !registry.valid.has(scopeKey);
|
|
15366
|
+
store.setState((state) => {
|
|
15367
|
+
const map = state[kind];
|
|
15368
|
+
if (scopeKey === ROOT_SCOPE) {
|
|
15369
|
+
if (!replace) return { [kind]: { ...map, ...staged } };
|
|
15370
|
+
const next = {};
|
|
15371
|
+
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15372
|
+
return { [kind]: { ...next, ...staged } };
|
|
15373
|
+
}
|
|
15374
|
+
const current = replace ? {} : map[scopeKey] ?? {};
|
|
15375
|
+
return { [kind]: { ...map, [scopeKey]: { ...current, ...staged } } };
|
|
15376
|
+
});
|
|
15377
|
+
registry.valid.add(scopeKey);
|
|
15378
|
+
}
|
|
15379
|
+
function invalidateResource(store, kind, scopeKey) {
|
|
15380
|
+
const registry = getKindRegistry(store, kind);
|
|
15381
|
+
if (scopeKey === void 0) {
|
|
15382
|
+
registry.valid.clear();
|
|
15383
|
+
registry.staged.clear();
|
|
15384
|
+
} else {
|
|
15385
|
+
registry.valid.delete(scopeKey);
|
|
15386
|
+
registry.staged.delete(scopeKey);
|
|
15387
|
+
}
|
|
15388
|
+
}
|
|
15389
|
+
function rebuildResource(store, kind, userScope) {
|
|
15390
|
+
const primary = resolvePrimary$1(store);
|
|
15391
|
+
invalidateResource(primary, kind, userScope === "root" ? ROOT_SCOPE : userScope);
|
|
15392
|
+
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
15393
|
+
}
|
|
15394
|
+
function invalidateAllResources(store) {
|
|
15395
|
+
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
15396
|
+
}
|
|
15397
|
+
function removeResourceEntries(store, kind, names, scope, isLeaf) {
|
|
15398
|
+
const staged = peekStaged(store, kind, scope ?? ROOT_SCOPE);
|
|
15399
|
+
if (staged) for (const name of names) delete staged[name];
|
|
15400
|
+
store.setState((state) => {
|
|
15401
|
+
const map = state[kind];
|
|
15402
|
+
if (scope) {
|
|
15403
|
+
const currentScope = { ...map[scope] };
|
|
15404
|
+
for (const name of names) delete currentScope[name];
|
|
15405
|
+
return { [kind]: { ...map, [scope]: currentScope } };
|
|
15406
|
+
}
|
|
15407
|
+
const next = { ...map };
|
|
15408
|
+
for (const name of names) if (isLeaf(next[name])) delete next[name];
|
|
15409
|
+
return { [kind]: next };
|
|
15410
|
+
});
|
|
15411
|
+
}
|
|
15412
|
+
function clearResourceEntries(store, kind, scope, isLeaf) {
|
|
15413
|
+
const registry = getKindRegistry(store, kind);
|
|
15414
|
+
if (scope && scope !== "root") registry.staged.delete(scope);
|
|
15415
|
+
else if (scope === "root") registry.staged.delete(ROOT_SCOPE);
|
|
15416
|
+
else registry.staged.clear();
|
|
15417
|
+
store.setState((state) => {
|
|
15418
|
+
const map = state[kind];
|
|
15419
|
+
if (scope && scope !== "root") {
|
|
15420
|
+
const { [scope]: _, ...rest } = map;
|
|
15421
|
+
return { [kind]: rest };
|
|
15422
|
+
}
|
|
15423
|
+
if (scope === "root") {
|
|
15424
|
+
const next = {};
|
|
15425
|
+
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15426
|
+
return { [kind]: next };
|
|
15427
|
+
}
|
|
15428
|
+
return { [kind]: {} };
|
|
15429
|
+
});
|
|
15430
|
+
}
|
|
15431
|
+
|
|
15432
|
+
const isObjectLike = (value) => value !== null && (typeof value === "object" || typeof value === "function");
|
|
15433
|
+
const hasValidLegacyNodeMarkers = (value) => {
|
|
15434
|
+
const hasUuid = "uuid" in value;
|
|
15435
|
+
const hasNodeType = "nodeType" in value;
|
|
15436
|
+
const uuid = Reflect.get(value, "uuid");
|
|
15437
|
+
const nodeType = Reflect.get(value, "nodeType");
|
|
15438
|
+
return (hasUuid || hasNodeType) && (!hasUuid || uuid === void 0 || typeof uuid === "string") && (!hasNodeType || nodeType === void 0 || nodeType === null || typeof nodeType === "string");
|
|
15439
|
+
};
|
|
15440
|
+
const isUniformNode = (value) => isObjectLike(value) && "isUniformNode" in value && value.isUniformNode === true;
|
|
15441
|
+
const isTSLNode = (value) => isObjectLike(value) && (Reflect.get(value, "isNode") === true || Reflect.get(value, "shaderNode") !== void 0 && typeof Reflect.get(value, "id") === "number" || hasValidLegacyNodeMarkers(value));
|
|
15442
|
+
const isBufferLike = (value) => ArrayBuffer.isView(value) && !(value instanceof DataView) || isObjectLike(value) && ("isBufferAttribute" in value || "isInterleavedBufferAttribute" in value || isTSLNode(value));
|
|
15443
|
+
const isStorageLike = (value) => isObjectLike(value) && ("isTexture" in value || "isData3DTexture" in value || isTSLNode(value));
|
|
15444
|
+
|
|
15312
15445
|
var __defProp = Object.defineProperty;
|
|
15313
15446
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
15314
15447
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
15315
|
-
var _a;
|
|
15448
|
+
var _a, _b;
|
|
15316
15449
|
const INTERNAL_DATA = Symbol("ScopedStore.data");
|
|
15317
|
-
|
|
15450
|
+
const INTERNAL_IS_LEAF = Symbol("ScopedStore.isLeaf");
|
|
15451
|
+
_b = INTERNAL_DATA, _a = INTERNAL_IS_LEAF;
|
|
15318
15452
|
const _ScopedStore = class _ScopedStore {
|
|
15319
|
-
constructor(data) {
|
|
15453
|
+
constructor(data, isLeaf) {
|
|
15454
|
+
__publicField(this, _b);
|
|
15320
15455
|
__publicField(this, _a);
|
|
15321
15456
|
this[INTERNAL_DATA] = data;
|
|
15457
|
+
this[INTERNAL_IS_LEAF] = isLeaf;
|
|
15322
15458
|
return new Proxy(this, {
|
|
15323
15459
|
get(target, prop, receiver) {
|
|
15324
15460
|
if (typeof prop === "string") {
|
|
@@ -15352,10 +15488,10 @@ const _ScopedStore = class _ScopedStore {
|
|
|
15352
15488
|
* If the key doesn't exist or isn't a scope object, returns an empty ScopedStore.
|
|
15353
15489
|
*/
|
|
15354
15490
|
scope(key) {
|
|
15355
|
-
const
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
);
|
|
15491
|
+
const value = this[INTERNAL_DATA][key];
|
|
15492
|
+
const isLeaf = this[INTERNAL_IS_LEAF];
|
|
15493
|
+
const scope = value && typeof value === "object" && !isLeaf(value) ? value : {};
|
|
15494
|
+
return new _ScopedStore(scope, isLeaf);
|
|
15359
15495
|
}
|
|
15360
15496
|
/**
|
|
15361
15497
|
* Check if a key exists in the store.
|
|
@@ -15371,8 +15507,8 @@ const _ScopedStore = class _ScopedStore {
|
|
|
15371
15507
|
}
|
|
15372
15508
|
};
|
|
15373
15509
|
let ScopedStore = _ScopedStore;
|
|
15374
|
-
function createScopedStore(data) {
|
|
15375
|
-
return new ScopedStore(data);
|
|
15510
|
+
function createScopedStore(data, isLeaf) {
|
|
15511
|
+
return new ScopedStore(data, isLeaf);
|
|
15376
15512
|
}
|
|
15377
15513
|
function createLazyCreatorState(state, store) {
|
|
15378
15514
|
let _uniforms = null;
|
|
@@ -15383,22 +15519,22 @@ function createLazyCreatorState(state, store) {
|
|
|
15383
15519
|
return Object.create(state, {
|
|
15384
15520
|
uniforms: {
|
|
15385
15521
|
get() {
|
|
15386
|
-
return _uniforms ?? (_uniforms = createScopedStore(view("uniforms")));
|
|
15522
|
+
return _uniforms ?? (_uniforms = createScopedStore(view("uniforms"), isUniformNode));
|
|
15387
15523
|
}
|
|
15388
15524
|
},
|
|
15389
15525
|
nodes: {
|
|
15390
15526
|
get() {
|
|
15391
|
-
return _nodes ?? (_nodes = createScopedStore(view("nodes")));
|
|
15527
|
+
return _nodes ?? (_nodes = createScopedStore(view("nodes"), isTSLNode));
|
|
15392
15528
|
}
|
|
15393
15529
|
},
|
|
15394
15530
|
buffers: {
|
|
15395
15531
|
get() {
|
|
15396
|
-
return _buffers ?? (_buffers = createScopedStore(view("buffers")));
|
|
15532
|
+
return _buffers ?? (_buffers = createScopedStore(view("buffers"), isBufferLike));
|
|
15397
15533
|
}
|
|
15398
15534
|
},
|
|
15399
15535
|
gpuStorage: {
|
|
15400
15536
|
get() {
|
|
15401
|
-
return _gpuStorage ?? (_gpuStorage = createScopedStore(view("gpuStorage")));
|
|
15537
|
+
return _gpuStorage ?? (_gpuStorage = createScopedStore(view("gpuStorage"), isStorageLike));
|
|
15402
15538
|
}
|
|
15403
15539
|
}
|
|
15404
15540
|
});
|
|
@@ -15418,44 +15554,10 @@ function usePrimaryThree(selector = (state) => state, equalityFn) {
|
|
|
15418
15554
|
return primary(selector, equalityFn);
|
|
15419
15555
|
}
|
|
15420
15556
|
|
|
15421
|
-
function
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
|
|
15425
|
-
return { textures: newMap };
|
|
15426
|
-
});
|
|
15427
|
-
}
|
|
15428
|
-
function addTextures(set, items) {
|
|
15429
|
-
set((state) => {
|
|
15430
|
-
const newMap = new Map(state.textures);
|
|
15431
|
-
const entries = items instanceof Map ? items.entries() : Object.entries(items);
|
|
15432
|
-
for (const [key, value] of entries) {
|
|
15433
|
-
newMap.set(key, value);
|
|
15434
|
-
}
|
|
15435
|
-
return { textures: newMap };
|
|
15436
|
-
});
|
|
15437
|
-
}
|
|
15438
|
-
function removeTexture(set, key) {
|
|
15439
|
-
set((state) => {
|
|
15440
|
-
const newMap = new Map(state.textures);
|
|
15441
|
-
newMap.delete(key);
|
|
15442
|
-
return { textures: newMap };
|
|
15443
|
-
});
|
|
15444
|
-
}
|
|
15445
|
-
function removeTextures(set, keys) {
|
|
15446
|
-
set((state) => {
|
|
15447
|
-
const newMap = new Map(state.textures);
|
|
15448
|
-
for (const key of keys) newMap.delete(key);
|
|
15449
|
-
return { textures: newMap };
|
|
15450
|
-
});
|
|
15451
|
-
}
|
|
15452
|
-
function createTextureOperations(set) {
|
|
15453
|
-
return {
|
|
15454
|
-
add: (key, value) => addTexture(set, key, value),
|
|
15455
|
-
addMultiple: (items) => addTextures(set, items),
|
|
15456
|
-
remove: (key) => removeTexture(set, key),
|
|
15457
|
-
removeMultiple: (keys) => removeTextures(set, keys)
|
|
15458
|
-
};
|
|
15557
|
+
function scopedNodeName(scope, name) {
|
|
15558
|
+
const raw = scope ? `${scope}_${name}` : name;
|
|
15559
|
+
const safe = raw.replace(/[^A-Za-z0-9_]/g, "_");
|
|
15560
|
+
return /^[A-Za-z_]/.test(safe) ? safe : `_${safe}`;
|
|
15459
15561
|
}
|
|
15460
15562
|
function extractTSLValue(value) {
|
|
15461
15563
|
if (value === null || value === void 0) return value;
|
|
@@ -15494,7 +15596,7 @@ function vectorize(inObject) {
|
|
|
15494
15596
|
return extractTSLValue(inObject);
|
|
15495
15597
|
}
|
|
15496
15598
|
if (obj.isVector2 || obj.isVector3 || obj.isVector4) return inObject;
|
|
15497
|
-
if (obj.isMatrix3 || obj.isMatrix4) return inObject;
|
|
15599
|
+
if (obj.isMatrix2 || obj.isMatrix3 || obj.isMatrix4) return inObject;
|
|
15498
15600
|
if (obj.isColor || obj.isEuler || obj.isQuaternion || obj.isSpherical) return inObject;
|
|
15499
15601
|
if ("r" in obj && "g" in obj && "b" in obj && typeof obj.r === "number" && typeof obj.g === "number" && typeof obj.b === "number") {
|
|
15500
15602
|
const scale = obj.r > 1 || obj.g > 1 || obj.b > 1 ? 1 / 255 : 1;
|
|
@@ -15521,6 +15623,47 @@ function useCompareMemoize(value, deep) {
|
|
|
15521
15623
|
return ref.current;
|
|
15522
15624
|
}
|
|
15523
15625
|
|
|
15626
|
+
function clearHmrCaches(store) {
|
|
15627
|
+
const primary = store.getState().primaryStore ?? store;
|
|
15628
|
+
invalidateAllResources(primary);
|
|
15629
|
+
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
15630
|
+
}
|
|
15631
|
+
|
|
15632
|
+
const SHARED_KEYS = ["uniforms", "nodes", "buffers", "gpuStorage", "_hmrVersion"];
|
|
15633
|
+
const following = /* @__PURE__ */ new WeakMap();
|
|
15634
|
+
function followPrimary(store) {
|
|
15635
|
+
const primary = store.getState().primaryStore;
|
|
15636
|
+
if (!primary || primary === store) return;
|
|
15637
|
+
const sync = () => {
|
|
15638
|
+
const source = primary.getState();
|
|
15639
|
+
const target = store.getState();
|
|
15640
|
+
let patch = null;
|
|
15641
|
+
for (const key of SHARED_KEYS) {
|
|
15642
|
+
if (target[key] !== source[key]) (patch ?? (patch = {}))[key] = source[key];
|
|
15643
|
+
}
|
|
15644
|
+
if (patch) store.setState(patch);
|
|
15645
|
+
};
|
|
15646
|
+
sync();
|
|
15647
|
+
following.set(store, primary.subscribe(sync));
|
|
15648
|
+
}
|
|
15649
|
+
function stopFollowing(store) {
|
|
15650
|
+
following.get(store)?.();
|
|
15651
|
+
following.delete(store);
|
|
15652
|
+
}
|
|
15653
|
+
let registered = false;
|
|
15654
|
+
function ensureTSLExtension() {
|
|
15655
|
+
if (registered) return;
|
|
15656
|
+
registered = true;
|
|
15657
|
+
registerRootExtension({
|
|
15658
|
+
name: "@react-three/tsl",
|
|
15659
|
+
setup: followPrimary,
|
|
15660
|
+
dispose: stopFollowing,
|
|
15661
|
+
// Resolves primaryStore itself, so every canvas sharing a renderer refreshes the same resources.
|
|
15662
|
+
hmr: clearHmrCaches
|
|
15663
|
+
});
|
|
15664
|
+
}
|
|
15665
|
+
|
|
15666
|
+
ensureTSLExtension();
|
|
15524
15667
|
function useScopedResource(options) {
|
|
15525
15668
|
const { store, kind, scope, isLeaf, create, prepare, reconcile, input } = options;
|
|
15526
15669
|
const scopeKey = scope ?? ROOT_SCOPE;
|
|
@@ -15552,22 +15695,21 @@ function useScopedResource(options) {
|
|
|
15552
15695
|
return entries;
|
|
15553
15696
|
}
|
|
15554
15697
|
|
|
15555
|
-
const isUniformNode$1 = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
|
|
15556
15698
|
function useUniforms(creatorOrScope, scope) {
|
|
15557
15699
|
const store = usePrimaryStore();
|
|
15558
15700
|
const removeUniforms2 = useCallback(
|
|
15559
|
-
(names, targetScope) => removeResourceEntries(store, "uniforms", Array.isArray(names) ? names : [names], targetScope, isUniformNode
|
|
15701
|
+
(names, targetScope) => removeResourceEntries(store, "uniforms", Array.isArray(names) ? names : [names], targetScope, isUniformNode),
|
|
15560
15702
|
[store]
|
|
15561
15703
|
);
|
|
15562
15704
|
const clearUniforms = useCallback(
|
|
15563
|
-
(targetScope) => clearResourceEntries(store, "uniforms", targetScope, isUniformNode
|
|
15705
|
+
(targetScope) => clearResourceEntries(store, "uniforms", targetScope, isUniformNode),
|
|
15564
15706
|
[store]
|
|
15565
15707
|
);
|
|
15566
15708
|
const rebuildUniforms = useCallback(
|
|
15567
15709
|
(targetScope) => rebuildResource(store, "uniforms", targetScope),
|
|
15568
15710
|
[store]
|
|
15569
15711
|
);
|
|
15570
|
-
const
|
|
15712
|
+
const processedInput = useMemo(() => {
|
|
15571
15713
|
let raw = creatorOrScope;
|
|
15572
15714
|
if (is.fun(creatorOrScope)) {
|
|
15573
15715
|
const wrappedState = createLazyCreatorState(store.getState(), store);
|
|
@@ -15578,23 +15720,24 @@ function useUniforms(creatorOrScope, scope) {
|
|
|
15578
15720
|
for (const [key, value] of Object.entries(raw)) {
|
|
15579
15721
|
normalized[key] = vectorize(value);
|
|
15580
15722
|
}
|
|
15581
|
-
return normalized;
|
|
15723
|
+
return { candidates: raw, normalized };
|
|
15582
15724
|
}
|
|
15583
|
-
return raw;
|
|
15725
|
+
return { candidates: raw, normalized: raw };
|
|
15584
15726
|
}, [creatorOrScope, store]);
|
|
15585
|
-
const memoizedInput = useCompareMemoize(
|
|
15727
|
+
const memoizedInput = useCompareMemoize(processedInput.normalized);
|
|
15586
15728
|
const isReader = memoizedInput === void 0 || typeof memoizedInput === "string";
|
|
15587
15729
|
const storeUniforms = usePrimaryThree((s) => s.uniforms);
|
|
15588
15730
|
const created = useScopedResource({
|
|
15589
15731
|
store,
|
|
15590
15732
|
kind: "uniforms",
|
|
15591
15733
|
scope: isReader ? void 0 : scope,
|
|
15592
|
-
isLeaf: isUniformNode
|
|
15734
|
+
isLeaf: isUniformNode,
|
|
15593
15735
|
input: memoizedInput,
|
|
15594
15736
|
create: () => {
|
|
15595
15737
|
if (isReader) return {};
|
|
15596
|
-
if (typeof
|
|
15597
|
-
|
|
15738
|
+
if (typeof processedInput.candidates !== "object" || processedInput.candidates === null)
|
|
15739
|
+
throw new Error("Invalid uniform input");
|
|
15740
|
+
return processedInput.candidates;
|
|
15598
15741
|
},
|
|
15599
15742
|
prepare: (name, candidate) => createUniform(name, candidate, scope),
|
|
15600
15743
|
reconcile: (existing, candidate) => {
|
|
@@ -15616,7 +15759,7 @@ function useUniforms(creatorOrScope, scope) {
|
|
|
15616
15759
|
uniforms = storeUniforms;
|
|
15617
15760
|
} else if (typeof memoizedInput === "string") {
|
|
15618
15761
|
const scopeData = storeUniforms[memoizedInput];
|
|
15619
|
-
uniforms = scopeData && !isUniformNode
|
|
15762
|
+
uniforms = scopeData && !isUniformNode(scopeData) ? scopeData : {};
|
|
15620
15763
|
}
|
|
15621
15764
|
return { ...uniforms, removeUniforms: removeUniforms2, clearUniforms, rebuildUniforms };
|
|
15622
15765
|
}
|
|
@@ -15631,7 +15774,7 @@ function removeUniforms(set, names, scope) {
|
|
|
15631
15774
|
return { uniforms: { ...state.uniforms, [scope]: currentScope } };
|
|
15632
15775
|
}
|
|
15633
15776
|
const uniforms = { ...state.uniforms };
|
|
15634
|
-
for (const name of names) if (isUniformNode
|
|
15777
|
+
for (const name of names) if (isUniformNode(uniforms[name])) delete uniforms[name];
|
|
15635
15778
|
return { uniforms };
|
|
15636
15779
|
});
|
|
15637
15780
|
}
|
|
@@ -15645,7 +15788,7 @@ function clearRootUniforms(set) {
|
|
|
15645
15788
|
set((state) => {
|
|
15646
15789
|
const uniforms = {};
|
|
15647
15790
|
for (const [key, value] of Object.entries(state.uniforms)) {
|
|
15648
|
-
if (!isUniformNode
|
|
15791
|
+
if (!isUniformNode(value)) uniforms[key] = value;
|
|
15649
15792
|
}
|
|
15650
15793
|
return { uniforms };
|
|
15651
15794
|
});
|
|
@@ -15655,8 +15798,7 @@ function createUniform(inName, node, scope) {
|
|
|
15655
15798
|
const inValue = vectorize(node);
|
|
15656
15799
|
const newUniform = uniform(inValue);
|
|
15657
15800
|
if (typeof newUniform.setName === "function") {
|
|
15658
|
-
|
|
15659
|
-
newUniform.setName(name);
|
|
15801
|
+
newUniform.setName(scopedNodeName(scope, inName));
|
|
15660
15802
|
}
|
|
15661
15803
|
return newUniform;
|
|
15662
15804
|
}
|
|
@@ -15682,14 +15824,12 @@ function hasEqualsMethod(value) {
|
|
|
15682
15824
|
function isSameThreeType(a, b) {
|
|
15683
15825
|
const obj_a = a;
|
|
15684
15826
|
const obj_b = b;
|
|
15685
|
-
return obj_a.isColor && obj_b.isColor || obj_a.isMatrix3 && obj_b.isMatrix3 || obj_a.isMatrix4 && obj_b.isMatrix4 || obj_a.isEuler && obj_b.isEuler || obj_a.isQuaternion && obj_b.isQuaternion;
|
|
15827
|
+
return obj_a.isColor && obj_b.isColor || obj_a.isMatrix2 && obj_b.isMatrix2 || obj_a.isMatrix3 && obj_b.isMatrix3 || obj_a.isMatrix4 && obj_b.isMatrix4 || obj_a.isEuler && obj_b.isEuler || obj_a.isQuaternion && obj_b.isQuaternion;
|
|
15686
15828
|
}
|
|
15687
15829
|
|
|
15688
15830
|
const uniformOf = uniform;
|
|
15689
|
-
const isUniformNode = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
|
|
15690
|
-
const isTSLNode$1 = (value) => value !== null && typeof value === "object" && "uuid" in value && "nodeType" in value;
|
|
15691
15831
|
function useUniform(name, value) {
|
|
15692
|
-
const store =
|
|
15832
|
+
const store = usePrimaryStore();
|
|
15693
15833
|
const registered = useScopedResource({
|
|
15694
15834
|
store,
|
|
15695
15835
|
kind: "uniforms",
|
|
@@ -15699,7 +15839,7 @@ function useUniform(name, value) {
|
|
|
15699
15839
|
create: () => value === void 0 ? {} : { [name]: value },
|
|
15700
15840
|
prepare: createNamedUniform,
|
|
15701
15841
|
reconcile: (existing2) => {
|
|
15702
|
-
if (value !== void 0 && !isTSLNode
|
|
15842
|
+
if (value !== void 0 && !isTSLNode(value) && !isUniformNode(value)) {
|
|
15703
15843
|
existing2.value = typeof value === "string" ? new Color(value) : value;
|
|
15704
15844
|
}
|
|
15705
15845
|
}
|
|
@@ -15715,7 +15855,7 @@ function createNamedUniform(name, value) {
|
|
|
15715
15855
|
let node;
|
|
15716
15856
|
if (isUniformNode(value)) {
|
|
15717
15857
|
node = value;
|
|
15718
|
-
} else if (isTSLNode
|
|
15858
|
+
} else if (isTSLNode(value)) {
|
|
15719
15859
|
node = uniformOf(value);
|
|
15720
15860
|
} else if (typeof value === "string") {
|
|
15721
15861
|
node = uniform(new Color(value));
|
|
@@ -15728,7 +15868,6 @@ function createNamedUniform(name, value) {
|
|
|
15728
15868
|
return node;
|
|
15729
15869
|
}
|
|
15730
15870
|
|
|
15731
|
-
const isTSLNode = (value) => value !== null && typeof value === "object" && ("uuid" in value || "nodeType" in value);
|
|
15732
15871
|
function useNodes(creatorOrScope, scope) {
|
|
15733
15872
|
const store = usePrimaryStore();
|
|
15734
15873
|
const removeNodes2 = useCallback(
|
|
@@ -15755,7 +15894,8 @@ function useNodes(creatorOrScope, scope) {
|
|
|
15755
15894
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15756
15895
|
},
|
|
15757
15896
|
prepare: (name, node) => {
|
|
15758
|
-
|
|
15897
|
+
const setName = Reflect.get(node, "setName");
|
|
15898
|
+
if (typeof setName === "function") setName.call(node, scopedNodeName(scope, name));
|
|
15759
15899
|
return node;
|
|
15760
15900
|
}
|
|
15761
15901
|
});
|
|
@@ -15810,13 +15950,6 @@ function useLocalNodes(creator) {
|
|
|
15810
15950
|
}, [store, creator, uniforms, nodes, textures, hmrVersion]);
|
|
15811
15951
|
}
|
|
15812
15952
|
|
|
15813
|
-
const isBufferLike = (value) => {
|
|
15814
|
-
if (value === null || typeof value !== "object") return false;
|
|
15815
|
-
if (ArrayBuffer.isView(value)) return true;
|
|
15816
|
-
if ("isBufferAttribute" in value) return true;
|
|
15817
|
-
if ("uuid" in value || "nodeType" in value) return true;
|
|
15818
|
-
return false;
|
|
15819
|
-
};
|
|
15820
15953
|
const disposeBuffer = (buffer) => {
|
|
15821
15954
|
if (buffer === null || typeof buffer !== "object") return;
|
|
15822
15955
|
if ("dispose" in buffer && typeof buffer.dispose === "function") {
|
|
@@ -15863,9 +15996,8 @@ function useBuffers(creatorOrScope, scope) {
|
|
|
15863
15996
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15864
15997
|
},
|
|
15865
15998
|
prepare: (name, buffer) => {
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
}
|
|
15999
|
+
const setName = Reflect.get(buffer, "setName");
|
|
16000
|
+
if (typeof setName === "function") setName.call(buffer, scopedNodeName(scope, name));
|
|
15869
16001
|
return buffer;
|
|
15870
16002
|
}
|
|
15871
16003
|
});
|
|
@@ -15882,13 +16014,6 @@ function rebuildAllBuffers(store, scope) {
|
|
|
15882
16014
|
rebuildResource(store, "buffers", scope);
|
|
15883
16015
|
}
|
|
15884
16016
|
|
|
15885
|
-
const isStorageLike = (value) => {
|
|
15886
|
-
if (value === null || typeof value !== "object") return false;
|
|
15887
|
-
if ("isTexture" in value) return true;
|
|
15888
|
-
if ("isData3DTexture" in value) return true;
|
|
15889
|
-
if ("uuid" in value || "nodeType" in value) return true;
|
|
15890
|
-
return false;
|
|
15891
|
-
};
|
|
15892
16017
|
const disposeStorage = (storage) => {
|
|
15893
16018
|
if (storage === null || typeof storage !== "object") return;
|
|
15894
16019
|
if ("dispose" in storage && typeof storage.dispose === "function") {
|
|
@@ -15935,10 +16060,9 @@ function useGPUStorage(creatorOrScope, scope) {
|
|
|
15935
16060
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15936
16061
|
},
|
|
15937
16062
|
prepare: (name, storage) => {
|
|
15938
|
-
const label = scope
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
}
|
|
16063
|
+
const label = scopedNodeName(scope, name);
|
|
16064
|
+
const setName = Reflect.get(storage, "setName");
|
|
16065
|
+
if (typeof setName === "function") setName.call(storage, label);
|
|
15942
16066
|
if ("name" in storage && typeof storage.name === "string") {
|
|
15943
16067
|
storage.name = label;
|
|
15944
16068
|
}
|
|
@@ -15964,11 +16088,58 @@ function rebuildAllStorage(store, scope) {
|
|
|
15964
16088
|
rebuildResource(store, "gpuStorage", scope);
|
|
15965
16089
|
}
|
|
15966
16090
|
|
|
16091
|
+
function addTexture(set, key, value) {
|
|
16092
|
+
set((state) => {
|
|
16093
|
+
const newMap = new Map(state.textures);
|
|
16094
|
+
newMap.set(key, value);
|
|
16095
|
+
return { textures: newMap };
|
|
16096
|
+
});
|
|
16097
|
+
}
|
|
16098
|
+
function addTextures(set, items) {
|
|
16099
|
+
set((state) => {
|
|
16100
|
+
const newMap = new Map(state.textures);
|
|
16101
|
+
const entries = items instanceof Map ? items.entries() : Object.entries(items);
|
|
16102
|
+
for (const [key, value] of entries) {
|
|
16103
|
+
newMap.set(key, value);
|
|
16104
|
+
}
|
|
16105
|
+
return { textures: newMap };
|
|
16106
|
+
});
|
|
16107
|
+
}
|
|
16108
|
+
function removeTexture(set, key) {
|
|
16109
|
+
set((state) => {
|
|
16110
|
+
const newMap = new Map(state.textures);
|
|
16111
|
+
newMap.delete(key);
|
|
16112
|
+
return { textures: newMap };
|
|
16113
|
+
});
|
|
16114
|
+
}
|
|
16115
|
+
function removeTextures(set, keys) {
|
|
16116
|
+
set((state) => {
|
|
16117
|
+
const newMap = new Map(state.textures);
|
|
16118
|
+
for (const key of keys) newMap.delete(key);
|
|
16119
|
+
return { textures: newMap };
|
|
16120
|
+
});
|
|
16121
|
+
}
|
|
16122
|
+
function createTextureOperations(set) {
|
|
16123
|
+
return {
|
|
16124
|
+
add: (key, value) => addTexture(set, key, value),
|
|
16125
|
+
addMultiple: (items) => addTextures(set, items),
|
|
16126
|
+
remove: (key) => removeTexture(set, key),
|
|
16127
|
+
removeMultiple: (keys) => removeTextures(set, keys)
|
|
16128
|
+
};
|
|
16129
|
+
}
|
|
16130
|
+
|
|
16131
|
+
function renderThroughPipeline(store) {
|
|
16132
|
+
return () => {
|
|
16133
|
+
const pipeline = store.getState().renderPipeline;
|
|
16134
|
+
if (pipeline?.render) pipeline.render();
|
|
16135
|
+
};
|
|
16136
|
+
}
|
|
15967
16137
|
function useRenderPipeline(mainCB, setupCB) {
|
|
15968
16138
|
const store = useStore();
|
|
15969
16139
|
const { scene, camera, renderer, isLegacy } = useThree$1();
|
|
15970
16140
|
const callbacksRanRef = useRef(false);
|
|
15971
16141
|
const scenePassCacheRef = useRef(null);
|
|
16142
|
+
const forceScenePassRebuildRef = useRef(false);
|
|
15972
16143
|
const mainCBRef = useRef(mainCB);
|
|
15973
16144
|
const setupCBRef = useRef(setupCB);
|
|
15974
16145
|
mainCBRef.current = mainCB;
|
|
@@ -15976,7 +16147,7 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15976
16147
|
const [rebuildVersion, setRebuildVersion] = useState(0);
|
|
15977
16148
|
useEffect(() => {
|
|
15978
16149
|
callbacksRanRef.current = false;
|
|
15979
|
-
|
|
16150
|
+
forceScenePassRebuildRef.current = true;
|
|
15980
16151
|
}, []);
|
|
15981
16152
|
const clearPasses = useCallback(() => {
|
|
15982
16153
|
store.setState({ passes: {} });
|
|
@@ -15986,12 +16157,15 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15986
16157
|
renderPipeline: null,
|
|
15987
16158
|
passes: {}
|
|
15988
16159
|
});
|
|
16160
|
+
setRenderOverride(store, null);
|
|
16161
|
+
scenePassCacheRef.current?.scenePass.dispose();
|
|
15989
16162
|
callbacksRanRef.current = false;
|
|
15990
16163
|
scenePassCacheRef.current = null;
|
|
16164
|
+
forceScenePassRebuildRef.current = false;
|
|
15991
16165
|
}, [store]);
|
|
15992
16166
|
const rebuild = useCallback(() => {
|
|
15993
16167
|
callbacksRanRef.current = false;
|
|
15994
|
-
|
|
16168
|
+
forceScenePassRebuildRef.current = true;
|
|
15995
16169
|
setRebuildVersion((v) => v + 1);
|
|
15996
16170
|
}, []);
|
|
15997
16171
|
useLayoutEffect(() => {
|
|
@@ -15999,6 +16173,9 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15999
16173
|
throw new Error("useRenderPipeline is only available with WebGPU renderer. Set renderer prop on Canvas.");
|
|
16000
16174
|
}
|
|
16001
16175
|
if (!renderer || !scene || !camera) return;
|
|
16176
|
+
if (!("isWebGPURenderer" in renderer)) {
|
|
16177
|
+
throw new Error("useRenderPipeline: renderer is not a WebGPURenderer but isLegacy is false.");
|
|
16178
|
+
}
|
|
16002
16179
|
const state = store.getState();
|
|
16003
16180
|
const set = store.setState;
|
|
16004
16181
|
try {
|
|
@@ -16009,21 +16186,34 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16009
16186
|
pipeline = new RenderPipeline(renderer);
|
|
16010
16187
|
justCreatedPipeline = true;
|
|
16011
16188
|
}
|
|
16012
|
-
const cacheValid = scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16189
|
+
const cacheValid = !forceScenePassRebuildRef.current && scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16190
|
+
let outgoingScenePass = null;
|
|
16013
16191
|
let scenePass;
|
|
16014
16192
|
if (cacheValid) {
|
|
16015
16193
|
scenePass = scenePassCacheRef.current.scenePass;
|
|
16016
16194
|
} else {
|
|
16195
|
+
outgoingScenePass = scenePassCacheRef.current?.scenePass ?? null;
|
|
16017
16196
|
scenePass = pass(scene, camera);
|
|
16018
16197
|
scenePassCacheRef.current = { sceneUuid: scene.uuid, cameraUuid: camera.uuid, scenePass };
|
|
16198
|
+
forceScenePassRebuildRef.current = false;
|
|
16019
16199
|
}
|
|
16020
16200
|
currentPasses.scenePass = scenePass;
|
|
16021
|
-
|
|
16201
|
+
let outputNodeChanged = false;
|
|
16202
|
+
if (!pipeline.outputNode || justCreatedPipeline || pipeline.outputNode === outgoingScenePass) {
|
|
16203
|
+
pipeline.outputNode = scenePass;
|
|
16204
|
+
outputNodeChanged = true;
|
|
16205
|
+
}
|
|
16022
16206
|
set({ renderPipeline: pipeline, passes: currentPasses });
|
|
16207
|
+
setRenderOverride(store, renderThroughPipeline(store));
|
|
16023
16208
|
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid;
|
|
16024
16209
|
if (shouldRunCallbacks) {
|
|
16025
16210
|
if (setupCBRef.current) {
|
|
16026
|
-
const freshState = store.getState()
|
|
16211
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16212
|
+
renderPipeline: pipeline,
|
|
16213
|
+
passes: { ...currentPasses, scenePass },
|
|
16214
|
+
renderer,
|
|
16215
|
+
isLegacy: false
|
|
16216
|
+
});
|
|
16027
16217
|
const setupResult = setupCBRef.current(freshState);
|
|
16028
16218
|
if (setupResult && typeof setupResult === "object") {
|
|
16029
16219
|
currentPasses = { ...currentPasses, ...setupResult };
|
|
@@ -16031,34 +16221,37 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16031
16221
|
}
|
|
16032
16222
|
}
|
|
16033
16223
|
if (mainCBRef.current) {
|
|
16034
|
-
const freshState = store.getState()
|
|
16224
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16225
|
+
renderPipeline: pipeline,
|
|
16226
|
+
passes: { ...currentPasses, scenePass },
|
|
16227
|
+
renderer,
|
|
16228
|
+
isLegacy: false
|
|
16229
|
+
});
|
|
16035
16230
|
const mainResult = mainCBRef.current(freshState);
|
|
16036
16231
|
if (mainResult && typeof mainResult === "object") {
|
|
16037
16232
|
currentPasses = { ...currentPasses, ...mainResult };
|
|
16038
16233
|
set({ passes: currentPasses });
|
|
16039
16234
|
}
|
|
16040
16235
|
}
|
|
16236
|
+
outputNodeChanged = true;
|
|
16041
16237
|
callbacksRanRef.current = true;
|
|
16042
16238
|
}
|
|
16239
|
+
if (outputNodeChanged) pipeline.needsUpdate = true;
|
|
16240
|
+
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose();
|
|
16043
16241
|
} catch (error) {
|
|
16044
16242
|
console.warn("[useRenderPipeline] Setup failed; the render pipeline was not configured:", error);
|
|
16045
16243
|
}
|
|
16046
16244
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16047
16245
|
const passes = useThree$1((s) => s.passes);
|
|
16048
16246
|
const renderPipeline = useThree$1((s) => s.renderPipeline);
|
|
16049
|
-
|
|
16050
|
-
|
|
16051
|
-
|
|
16052
|
-
clearPasses,
|
|
16053
|
-
reset,
|
|
16054
|
-
rebuild,
|
|
16055
|
-
// isReady indicates if RenderPipeline is configured and ready for rendering
|
|
16056
|
-
isReady: renderPipeline !== null
|
|
16057
|
-
};
|
|
16247
|
+
const actions = { passes, clearPasses, reset, rebuild };
|
|
16248
|
+
if (renderPipeline) return { ...actions, isReady: true, renderPipeline };
|
|
16249
|
+
return { ...actions, isReady: false, renderPipeline: null };
|
|
16058
16250
|
}
|
|
16059
16251
|
|
|
16060
16252
|
extend(THREE);
|
|
16061
16253
|
const useThree = useThree$1;
|
|
16062
16254
|
const useFrame = useFrame$1;
|
|
16255
|
+
const Canvas = Canvas$1;
|
|
16063
16256
|
|
|
16064
|
-
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, clearNodeScope, clearRootNodes, clearRootUniforms, clearScope, context, createEvents, createPointerEvents, createPortal, createRoot, createScopedStore, createStore, createTextureOperations, 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, rebuildAllBuffers, rebuildAllNodes, rebuildAllStorage, rebuildAllUniforms, reconciler, registerPrimary, removeInteractivity, removeNodes, removeUniforms, resolve, swapInteractivity, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useBuffers, useEnvironment, useFrame, useGPUStorage, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, useRenderPipeline, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms, waitForPrimary };
|
|
16257
|
+
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, clearNodeScope, clearRootNodes, clearRootUniforms, clearScope, context, createEvents, createPointerEvents, createPortal, createRoot, createScopedStore, createStore, createTextureOperations, 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, rebuildAllBuffers, rebuildAllNodes, rebuildAllStorage, rebuildAllUniforms, reconciler, registerPrimary, registerRootExtension, removeInteractivity, removeNodes, removeUniforms, resolve, setRenderOverride, swapInteractivity, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useBuffers, useEnvironment, useFrame, useGPUStorage, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, useRenderPipeline, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms, waitForPrimary };
|