@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.cjs
CHANGED
|
@@ -10,6 +10,7 @@ const scheduler = require('@pmndrs/scheduler');
|
|
|
10
10
|
const Tb = require('scheduler');
|
|
11
11
|
const GroundedSkybox_js = require('three/examples/jsm/objects/GroundedSkybox.js');
|
|
12
12
|
const HDRLoader_js = require('three/examples/jsm/loaders/HDRLoader.js');
|
|
13
|
+
const HDRCubeTextureLoader_js = require('three/examples/jsm/loaders/HDRCubeTextureLoader.js');
|
|
13
14
|
const EXRLoader_js = require('three/examples/jsm/loaders/EXRLoader.js');
|
|
14
15
|
const UltraHDRLoader_js = require('three/examples/jsm/loaders/UltraHDRLoader.js');
|
|
15
16
|
const gainmapJs = require('@monogrid/gainmap-js');
|
|
@@ -323,7 +324,6 @@ function prepare(target, root, type, props) {
|
|
|
323
324
|
}
|
|
324
325
|
function invalidateInstance(instance) {
|
|
325
326
|
if (!instance.parent) return;
|
|
326
|
-
instance.props.onUpdate?.(instance.object);
|
|
327
327
|
const state = instance.root?.getState?.();
|
|
328
328
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
329
329
|
}
|
|
@@ -539,8 +539,10 @@ function hasVisibilityHandlers(handlers) {
|
|
|
539
539
|
}
|
|
540
540
|
|
|
541
541
|
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
542
|
-
function fromRef(ref) {
|
|
543
|
-
|
|
542
|
+
function fromRef(ref, transform) {
|
|
543
|
+
const marker = { [FROM_REF]: ref };
|
|
544
|
+
if (transform) marker.transform = transform;
|
|
545
|
+
return marker;
|
|
544
546
|
}
|
|
545
547
|
function isFromRef(value) {
|
|
546
548
|
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
@@ -554,6 +556,63 @@ function isOnce(value) {
|
|
|
554
556
|
return value !== null && typeof value === "object" && ONCE in value;
|
|
555
557
|
}
|
|
556
558
|
|
|
559
|
+
const shownNotices = /* @__PURE__ */ new Set();
|
|
560
|
+
function notifyDepreciated({ heading, body, link }) {
|
|
561
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (shownNotices.has(heading)) return;
|
|
565
|
+
shownNotices.add(heading);
|
|
566
|
+
const caller = getCallerFrame();
|
|
567
|
+
if (caller) {
|
|
568
|
+
console.log();
|
|
569
|
+
}
|
|
570
|
+
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
571
|
+
if (caller) {
|
|
572
|
+
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
573
|
+
}
|
|
574
|
+
if (body || link) {
|
|
575
|
+
let message = "";
|
|
576
|
+
if (body) message += body;
|
|
577
|
+
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
578
|
+
console.warn(`%c${message}`, "font-weight: bold;");
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
function getCallerFrame(depth = 3) {
|
|
582
|
+
const stack = new Error().stack;
|
|
583
|
+
if (!stack) return null;
|
|
584
|
+
const lines = stack.split("\n");
|
|
585
|
+
const frame = lines[depth];
|
|
586
|
+
if (!frame) return null;
|
|
587
|
+
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
588
|
+
if (!match) {
|
|
589
|
+
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
590
|
+
}
|
|
591
|
+
if (!match) return null;
|
|
592
|
+
const [, fn, url, line] = match;
|
|
593
|
+
return {
|
|
594
|
+
functionName: fn ?? "<anonymous>",
|
|
595
|
+
location: formatLocation(url, Number(line))
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function formatLocation(url, line) {
|
|
599
|
+
const clean = url.split("?")[0];
|
|
600
|
+
const file = clean.split("/").pop() ?? clean;
|
|
601
|
+
return `${file}:${line}`;
|
|
602
|
+
}
|
|
603
|
+
function notifyAlpha({ message, link }) {
|
|
604
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (shownNotices.has(message)) return;
|
|
608
|
+
shownNotices.add(message);
|
|
609
|
+
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
610
|
+
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
611
|
+
{
|
|
612
|
+
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
557
616
|
const RESERVED_PROPS = [
|
|
558
617
|
"children",
|
|
559
618
|
"key",
|
|
@@ -563,7 +622,6 @@ const RESERVED_PROPS = [
|
|
|
563
622
|
"dispose",
|
|
564
623
|
"attach",
|
|
565
624
|
"object",
|
|
566
|
-
"onUpdate",
|
|
567
625
|
// Behavior flags
|
|
568
626
|
"dispose"
|
|
569
627
|
];
|
|
@@ -641,11 +699,9 @@ function diffProps(instance, newProps) {
|
|
|
641
699
|
for (const prop in instance.props) {
|
|
642
700
|
if (RESERVED_PROPS.includes(prop) || newProps.hasOwnProperty(prop)) continue;
|
|
643
701
|
const { root, key } = resolve(instance.object, prop);
|
|
644
|
-
if (
|
|
702
|
+
if (typeof root?.constructor === "function") {
|
|
645
703
|
const ctor = getMemoizedPrototype(root);
|
|
646
704
|
if (!is.und(ctor)) changedProps[prop] = ctor[key];
|
|
647
|
-
} else {
|
|
648
|
-
changedProps[prop] = 0;
|
|
649
705
|
}
|
|
650
706
|
}
|
|
651
707
|
return changedProps;
|
|
@@ -657,6 +713,13 @@ function applyProps(object, props) {
|
|
|
657
713
|
for (const prop in props) {
|
|
658
714
|
const value = props[prop];
|
|
659
715
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
716
|
+
if (prop === "onUpdate") {
|
|
717
|
+
notifyDepreciated({
|
|
718
|
+
heading: "onUpdate is no longer an R3F prop",
|
|
719
|
+
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.",
|
|
720
|
+
link: "https://docs.pmnd.rs/react-three-fiber/migration/v10#onupdate-removed"
|
|
721
|
+
});
|
|
722
|
+
}
|
|
660
723
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
661
724
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
662
725
|
else delete instance.handlers[prop];
|
|
@@ -731,377 +794,48 @@ function applyProps(object, props) {
|
|
|
731
794
|
}
|
|
732
795
|
}
|
|
733
796
|
if (instance?.parent && rootState?.internal && instance.object?.isObject3D && prevHandlers !== instance.eventCount) {
|
|
734
|
-
const object2 = instance.object;
|
|
735
|
-
const index = rootState.internal.interaction.indexOf(object2);
|
|
736
|
-
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
737
|
-
if (instance.eventCount && object2.raycast !== null) {
|
|
738
|
-
rootState.internal.interaction.push(object2);
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
if (instance?.parent && rootState?.internal && instance.object?.isObject3D) {
|
|
742
|
-
const object2 = instance.object;
|
|
743
|
-
const root = findInitialRoot(instance);
|
|
744
|
-
const visibilityHandlers = {
|
|
745
|
-
onFramed: instance.handlers.onFramed,
|
|
746
|
-
onOccluded: instance.handlers.onOccluded,
|
|
747
|
-
onVisible: instance.handlers.onVisible
|
|
748
|
-
};
|
|
749
|
-
if (hasVisibilityHandlers(visibilityHandlers)) {
|
|
750
|
-
if (!updateVisibilityHandlers(root, object2, visibilityHandlers)) {
|
|
751
|
-
registerVisibility(root, object2, visibilityHandlers);
|
|
752
|
-
}
|
|
753
|
-
} else {
|
|
754
|
-
unregisterVisibility(root, object2);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
if (instance && instance.props.attach === void 0) {
|
|
758
|
-
if (instance.object.isBufferGeometry) instance.props.attach = "geometry";
|
|
759
|
-
else if (instance.object.isMaterial) instance.props.attach = "material";
|
|
760
|
-
}
|
|
761
|
-
if (instance) invalidateInstance(instance);
|
|
762
|
-
return object;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
const shownNotices = /* @__PURE__ */ new Set();
|
|
766
|
-
function notifyDepreciated({ heading, body, link }) {
|
|
767
|
-
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_DEPRECATION_WARNINGS !== "true") {
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
|
-
if (shownNotices.has(heading)) return;
|
|
771
|
-
shownNotices.add(heading);
|
|
772
|
-
const caller = getCallerFrame();
|
|
773
|
-
if (caller) {
|
|
774
|
-
console.log();
|
|
775
|
-
}
|
|
776
|
-
const boxStyle = "background: #ff9800; color: #1a1a1a; padding: 8px 12px; border-radius: 4px; font-weight: 500;";
|
|
777
|
-
if (caller) {
|
|
778
|
-
console.log(`%c\u26A0\uFE0F ${heading}`, boxStyle);
|
|
779
|
-
}
|
|
780
|
-
if (body || link) {
|
|
781
|
-
let message = "";
|
|
782
|
-
if (body) message += body;
|
|
783
|
-
if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
|
|
784
|
-
console.warn(`%c${message}`, "font-weight: bold;");
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
function getCallerFrame(depth = 3) {
|
|
788
|
-
const stack = new Error().stack;
|
|
789
|
-
if (!stack) return null;
|
|
790
|
-
const lines = stack.split("\n");
|
|
791
|
-
const frame = lines[depth];
|
|
792
|
-
if (!frame) return null;
|
|
793
|
-
let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
|
|
794
|
-
if (!match) {
|
|
795
|
-
match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
|
|
796
|
-
}
|
|
797
|
-
if (!match) return null;
|
|
798
|
-
const [, fn, url, line] = match;
|
|
799
|
-
return {
|
|
800
|
-
functionName: fn ?? "<anonymous>",
|
|
801
|
-
location: formatLocation(url, Number(line))
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
function formatLocation(url, line) {
|
|
805
|
-
const clean = url.split("?")[0];
|
|
806
|
-
const file = clean.split("/").pop() ?? clean;
|
|
807
|
-
return `${file}:${line}`;
|
|
808
|
-
}
|
|
809
|
-
function notifyAlpha({ message, link }) {
|
|
810
|
-
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
if (shownNotices.has(message)) return;
|
|
814
|
-
shownNotices.add(message);
|
|
815
|
-
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
816
|
-
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
817
|
-
{
|
|
818
|
-
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
823
|
-
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
824
|
-
if (!stack) return false;
|
|
825
|
-
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
826
|
-
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
830
|
-
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React__namespace.createContext(null));
|
|
831
|
-
const createStore = (invalidate, advance) => {
|
|
832
|
-
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
833
|
-
const position = new webgpu.Vector3();
|
|
834
|
-
const defaultTarget = new webgpu.Vector3();
|
|
835
|
-
const tempTarget = new webgpu.Vector3();
|
|
836
|
-
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
837
|
-
const { width, height, top, left } = size;
|
|
838
|
-
const aspect = width / height;
|
|
839
|
-
if (target.isVector3) tempTarget.copy(target);
|
|
840
|
-
else tempTarget.set(...target);
|
|
841
|
-
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
842
|
-
if (isOrthographicCamera(camera)) {
|
|
843
|
-
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
844
|
-
} else {
|
|
845
|
-
const fov = camera.fov * Math.PI / 180;
|
|
846
|
-
const h = 2 * Math.tan(fov / 2) * distance;
|
|
847
|
-
const w = h * (width / height);
|
|
848
|
-
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
let performanceTimeout = void 0;
|
|
852
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
853
|
-
const pointer = new webgpu.Vector2();
|
|
854
|
-
const rootState = {
|
|
855
|
-
set,
|
|
856
|
-
get,
|
|
857
|
-
// Mock objects that have to be configured
|
|
858
|
-
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
859
|
-
primaryStore: null,
|
|
860
|
-
gl: null,
|
|
861
|
-
renderer: null,
|
|
862
|
-
camera: null,
|
|
863
|
-
frustum: new webgpu.Frustum(),
|
|
864
|
-
autoUpdateFrustum: true,
|
|
865
|
-
raycaster: null,
|
|
866
|
-
events: {
|
|
867
|
-
priority: 1,
|
|
868
|
-
enabled: true,
|
|
869
|
-
connected: false,
|
|
870
|
-
frameTimedRaycasts: true,
|
|
871
|
-
alwaysFireOnScroll: true,
|
|
872
|
-
updateOnFrame: false
|
|
873
|
-
},
|
|
874
|
-
scene: null,
|
|
875
|
-
rootScene: null,
|
|
876
|
-
xr: null,
|
|
877
|
-
inspector: null,
|
|
878
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
879
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
880
|
-
textureColorSpace: webgpu.SRGBColorSpace,
|
|
881
|
-
isLegacy: false,
|
|
882
|
-
webGPUSupported: false,
|
|
883
|
-
isNative: false,
|
|
884
|
-
controls: null,
|
|
885
|
-
pointer,
|
|
886
|
-
mouse: pointer,
|
|
887
|
-
frameloop: "always",
|
|
888
|
-
onPointerMissed: void 0,
|
|
889
|
-
onDragOverMissed: void 0,
|
|
890
|
-
onDropMissed: void 0,
|
|
891
|
-
performance: {
|
|
892
|
-
current: 1,
|
|
893
|
-
min: 0.5,
|
|
894
|
-
max: 1,
|
|
895
|
-
debounce: 200,
|
|
896
|
-
regress: () => {
|
|
897
|
-
const state2 = get();
|
|
898
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
899
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
900
|
-
performanceTimeout = setTimeout(
|
|
901
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
902
|
-
state2.performance.debounce
|
|
903
|
-
);
|
|
904
|
-
}
|
|
905
|
-
},
|
|
906
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
907
|
-
viewport: {
|
|
908
|
-
initialDpr: 0,
|
|
909
|
-
dpr: 0,
|
|
910
|
-
width: 0,
|
|
911
|
-
height: 0,
|
|
912
|
-
top: 0,
|
|
913
|
-
left: 0,
|
|
914
|
-
aspect: 0,
|
|
915
|
-
distance: 0,
|
|
916
|
-
factor: 0,
|
|
917
|
-
getCurrentViewport
|
|
918
|
-
},
|
|
919
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
920
|
-
setSize: (width, height, top, left) => {
|
|
921
|
-
const state2 = get();
|
|
922
|
-
if (width === void 0) {
|
|
923
|
-
set({ _sizeImperative: false });
|
|
924
|
-
if (state2._sizeProps) {
|
|
925
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
926
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
927
|
-
const currentSize = state2.size;
|
|
928
|
-
const newSize = {
|
|
929
|
-
width: propW ?? currentSize.width,
|
|
930
|
-
height: propH ?? currentSize.height,
|
|
931
|
-
top: currentSize.top,
|
|
932
|
-
left: currentSize.left
|
|
933
|
-
};
|
|
934
|
-
set((s) => ({
|
|
935
|
-
size: newSize,
|
|
936
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
937
|
-
}));
|
|
938
|
-
scheduler.getScheduler().invalidate();
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
return;
|
|
942
|
-
}
|
|
943
|
-
const w = width;
|
|
944
|
-
const h = height ?? width;
|
|
945
|
-
const t = top ?? state2.size.top;
|
|
946
|
-
const l = left ?? state2.size.left;
|
|
947
|
-
const size = { width: w, height: h, top: t, left: l };
|
|
948
|
-
set((s) => ({
|
|
949
|
-
size,
|
|
950
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
951
|
-
_sizeImperative: true
|
|
952
|
-
}));
|
|
953
|
-
scheduler.getScheduler().invalidate();
|
|
954
|
-
},
|
|
955
|
-
setDpr: (dpr) => set((state2) => {
|
|
956
|
-
const resolved = calculateDpr(dpr);
|
|
957
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
958
|
-
}),
|
|
959
|
-
setFrameloop: (frameloop = "always") => {
|
|
960
|
-
set(() => ({ frameloop }));
|
|
961
|
-
scheduler.getScheduler().frameloop = frameloop;
|
|
962
|
-
},
|
|
963
|
-
setError: (error) => set(() => ({ error })),
|
|
964
|
-
error: null,
|
|
965
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
966
|
-
uniforms: {},
|
|
967
|
-
nodes: {},
|
|
968
|
-
buffers: {},
|
|
969
|
-
gpuStorage: {},
|
|
970
|
-
textures: /* @__PURE__ */ new Map(),
|
|
971
|
-
_textureRefs: /* @__PURE__ */ new Map(),
|
|
972
|
-
renderPipeline: null,
|
|
973
|
-
passes: {},
|
|
974
|
-
_hmrVersion: 0,
|
|
975
|
-
_sizeImperative: false,
|
|
976
|
-
_sizeProps: null,
|
|
977
|
-
previousRoot: void 0,
|
|
978
|
-
internal: {
|
|
979
|
-
// Events
|
|
980
|
-
interaction: [],
|
|
981
|
-
subscribers: [],
|
|
982
|
-
// Per-pointer state (new unified structure)
|
|
983
|
-
pointerMap: /* @__PURE__ */ new Map(),
|
|
984
|
-
pointerDirty: /* @__PURE__ */ new Map(),
|
|
985
|
-
lastEvent: React__namespace.createRef(),
|
|
986
|
-
// Deprecated but kept for backwards compatibility
|
|
987
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
988
|
-
initialClick: [0, 0],
|
|
989
|
-
initialHits: [],
|
|
990
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
991
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
992
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
993
|
-
// Occlusion system (WebGPU only)
|
|
994
|
-
occlusionEnabled: false,
|
|
995
|
-
occlusionObserver: null,
|
|
996
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
997
|
-
helperGroup: null,
|
|
998
|
-
// Updates
|
|
999
|
-
active: false,
|
|
1000
|
-
frames: 0,
|
|
1001
|
-
priority: 0,
|
|
1002
|
-
subscribe: (ref, priority, store) => {
|
|
1003
|
-
const internal = get().internal;
|
|
1004
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1005
|
-
internal.subscribers.push({ ref, priority, store });
|
|
1006
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1007
|
-
return () => {
|
|
1008
|
-
const internal2 = get().internal;
|
|
1009
|
-
if (internal2?.subscribers) {
|
|
1010
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
1011
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
1012
|
-
}
|
|
1013
|
-
};
|
|
1014
|
-
},
|
|
1015
|
-
// Renderer Storage (single source of truth)
|
|
1016
|
-
actualRenderer: null,
|
|
1017
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
1018
|
-
scheduler: null
|
|
1019
|
-
}
|
|
1020
|
-
};
|
|
1021
|
-
return rootState;
|
|
1022
|
-
});
|
|
1023
|
-
const state = rootStore.getState();
|
|
1024
|
-
Object.defineProperty(state, "gl", {
|
|
1025
|
-
get() {
|
|
1026
|
-
const currentState = rootStore.getState();
|
|
1027
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1028
|
-
const stack = new Error().stack || "";
|
|
1029
|
-
if (!isInternalRendererAccess(stack)) {
|
|
1030
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1031
|
-
notifyDepreciated({
|
|
1032
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1033
|
-
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
|
|
1034
|
-
});
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
return currentState.internal.actualRenderer;
|
|
1038
|
-
},
|
|
1039
|
-
set(value) {
|
|
1040
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1041
|
-
},
|
|
1042
|
-
enumerable: true,
|
|
1043
|
-
configurable: true
|
|
1044
|
-
});
|
|
1045
|
-
Object.defineProperty(state, "renderer", {
|
|
1046
|
-
get() {
|
|
1047
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1048
|
-
},
|
|
1049
|
-
set(value) {
|
|
1050
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1051
|
-
},
|
|
1052
|
-
enumerable: true,
|
|
1053
|
-
configurable: true
|
|
1054
|
-
});
|
|
1055
|
-
let oldScene = state.scene;
|
|
1056
|
-
rootStore.subscribe(() => {
|
|
1057
|
-
const currentState = rootStore.getState();
|
|
1058
|
-
const { scene, rootScene, set } = currentState;
|
|
1059
|
-
if (scene !== oldScene) {
|
|
1060
|
-
oldScene = scene;
|
|
1061
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1062
|
-
set({ rootScene: scene });
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
});
|
|
1066
|
-
let oldSize = state.size;
|
|
1067
|
-
let oldDpr = state.viewport.dpr;
|
|
1068
|
-
let oldCamera = state.camera;
|
|
1069
|
-
rootStore.subscribe(() => {
|
|
1070
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1071
|
-
const actualRenderer = internal.actualRenderer;
|
|
1072
|
-
const canvasTarget = internal.canvasTarget;
|
|
1073
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1074
|
-
oldSize = size;
|
|
1075
|
-
oldDpr = viewport.dpr;
|
|
1076
|
-
updateCamera(camera, size);
|
|
1077
|
-
if (internal.isSecondary && canvasTarget) {
|
|
1078
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1079
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1080
|
-
} else {
|
|
1081
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1082
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1083
|
-
if (canvasTarget) {
|
|
1084
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1085
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
if (camera !== oldCamera) {
|
|
1090
|
-
oldCamera = camera;
|
|
1091
|
-
const { rootScene } = rootStore.getState();
|
|
1092
|
-
if (camera && rootScene && !camera.parent) {
|
|
1093
|
-
rootScene.add(camera);
|
|
1094
|
-
}
|
|
1095
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1096
|
-
const currentState = rootStore.getState();
|
|
1097
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1098
|
-
updateFrustum(camera, currentState.frustum);
|
|
797
|
+
const object2 = instance.object;
|
|
798
|
+
const index = rootState.internal.interaction.indexOf(object2);
|
|
799
|
+
if (index > -1) rootState.internal.interaction.splice(index, 1);
|
|
800
|
+
if (instance.eventCount && object2.raycast !== null) {
|
|
801
|
+
rootState.internal.interaction.push(object2);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
if (instance?.parent && rootState?.internal && instance.object?.isObject3D) {
|
|
805
|
+
const object2 = instance.object;
|
|
806
|
+
const root = findInitialRoot(instance);
|
|
807
|
+
const visibilityHandlers = {
|
|
808
|
+
onFramed: instance.handlers.onFramed,
|
|
809
|
+
onOccluded: instance.handlers.onOccluded,
|
|
810
|
+
onVisible: instance.handlers.onVisible
|
|
811
|
+
};
|
|
812
|
+
if (hasVisibilityHandlers(visibilityHandlers)) {
|
|
813
|
+
if (!updateVisibilityHandlers(root, object2, visibilityHandlers)) {
|
|
814
|
+
registerVisibility(root, object2, visibilityHandlers);
|
|
1099
815
|
}
|
|
816
|
+
} else {
|
|
817
|
+
unregisterVisibility(root, object2);
|
|
1100
818
|
}
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
819
|
+
}
|
|
820
|
+
if (instance && instance.props.attach === void 0) {
|
|
821
|
+
if (instance.object.isBufferGeometry) instance.props.attach = "geometry";
|
|
822
|
+
else if (instance.object.isMaterial) instance.props.attach = "material";
|
|
823
|
+
}
|
|
824
|
+
if (instance) invalidateInstance(instance);
|
|
825
|
+
return object;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
829
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React__namespace.createContext(null));
|
|
830
|
+
|
|
831
|
+
function useStore() {
|
|
832
|
+
const store = React.useContext(context);
|
|
833
|
+
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
834
|
+
return store;
|
|
835
|
+
}
|
|
836
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
837
|
+
return useStore()(selector, equalityFn);
|
|
838
|
+
}
|
|
1105
839
|
|
|
1106
840
|
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
1107
841
|
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
@@ -1146,7 +880,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1146
880
|
const results = cacheKeys.map(
|
|
1147
881
|
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1148
882
|
);
|
|
1149
|
-
|
|
883
|
+
const stableRef = React.useRef(null);
|
|
884
|
+
const previous = stableRef.current;
|
|
885
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
886
|
+
stableRef.current = stable;
|
|
887
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1150
888
|
}
|
|
1151
889
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1152
890
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1266,6 +1004,13 @@ function useFrame$1(callback, priorityOrOptions) {
|
|
|
1266
1004
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1267
1005
|
*/
|
|
1268
1006
|
scheduler: scheduler2,
|
|
1007
|
+
/**
|
|
1008
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
1009
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1010
|
+
*/
|
|
1011
|
+
get rootId() {
|
|
1012
|
+
return scheduler.getScheduler().getJobRootId(id);
|
|
1013
|
+
},
|
|
1269
1014
|
/**
|
|
1270
1015
|
* Manually step this job only.
|
|
1271
1016
|
* Bypasses FPS limiting - always runs.
|
|
@@ -1282,6 +1027,14 @@ function useFrame$1(callback, priorityOrOptions) {
|
|
|
1282
1027
|
stepAll: (timestamp) => {
|
|
1283
1028
|
scheduler.getScheduler().step(timestamp);
|
|
1284
1029
|
},
|
|
1030
|
+
/**
|
|
1031
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1032
|
+
*/
|
|
1033
|
+
invalidate: (frames, stackFrames) => {
|
|
1034
|
+
const scheduler3 = scheduler.getScheduler();
|
|
1035
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1036
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1037
|
+
},
|
|
1285
1038
|
/**
|
|
1286
1039
|
* Pause this job (set enabled=false).
|
|
1287
1040
|
* Job remains registered but won't run.
|
|
@@ -1311,6 +1064,11 @@ function getUrls(input) {
|
|
|
1311
1064
|
if (Array.isArray(input)) return input;
|
|
1312
1065
|
return Object.values(input);
|
|
1313
1066
|
}
|
|
1067
|
+
function inputSignature(input) {
|
|
1068
|
+
if (typeof input === "string") return input;
|
|
1069
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1070
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1071
|
+
}
|
|
1314
1072
|
function allUrlsCached(urls, textureCache) {
|
|
1315
1073
|
return urls.every((url) => textureCache.has(url));
|
|
1316
1074
|
}
|
|
@@ -1336,24 +1094,37 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1336
1094
|
const onLoadRef = React.useRef(onLoad);
|
|
1337
1095
|
onLoadRef.current = onLoad;
|
|
1338
1096
|
const onLoadCalledForRef = React.useRef(null);
|
|
1339
|
-
const
|
|
1097
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
1098
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
1099
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1340
1100
|
const cachedResult = React.useMemo(() => {
|
|
1341
1101
|
if (!cache) return null;
|
|
1342
1102
|
const textures = store.getState().textures;
|
|
1343
1103
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1344
|
-
return buildFromCache(
|
|
1345
|
-
}, [cache, urls,
|
|
1104
|
+
return buildFromCache(stableInput, textures);
|
|
1105
|
+
}, [cache, urls, stableInput, store]);
|
|
1346
1106
|
const loadedTextures = useLoader(
|
|
1347
1107
|
webgpu.TextureLoader,
|
|
1348
|
-
IsObject(
|
|
1108
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1349
1109
|
);
|
|
1350
|
-
const
|
|
1110
|
+
const mappedTextures = React.useMemo(() => {
|
|
1111
|
+
if (cachedResult) return cachedResult;
|
|
1112
|
+
if (IsObject(stableInput)) {
|
|
1113
|
+
const keyed = {};
|
|
1114
|
+
const textureArray = loadedTextures;
|
|
1115
|
+
let i = 0;
|
|
1116
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1117
|
+
return keyed;
|
|
1118
|
+
} else {
|
|
1119
|
+
return loadedTextures;
|
|
1120
|
+
}
|
|
1121
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1351
1122
|
React.useLayoutEffect(() => {
|
|
1352
1123
|
if (cachedResult) return;
|
|
1353
1124
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
1354
1125
|
onLoadCalledForRef.current = inputKey;
|
|
1355
|
-
onLoadRef.current?.(
|
|
1356
|
-
}, [cachedResult,
|
|
1126
|
+
onLoadRef.current?.(mappedTextures);
|
|
1127
|
+
}, [cachedResult, mappedTextures, inputKey]);
|
|
1357
1128
|
React.useEffect(() => {
|
|
1358
1129
|
if (cachedResult) return;
|
|
1359
1130
|
if ("initTexture" in renderer) {
|
|
@@ -1372,30 +1143,18 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1372
1143
|
});
|
|
1373
1144
|
}
|
|
1374
1145
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1375
|
-
const mappedTextures = React.useMemo(() => {
|
|
1376
|
-
if (cachedResult) return cachedResult;
|
|
1377
|
-
if (IsObject(input)) {
|
|
1378
|
-
const keyed = {};
|
|
1379
|
-
const textureArray = loadedTextures;
|
|
1380
|
-
let i = 0;
|
|
1381
|
-
for (const key in input) keyed[key] = textureArray[i++];
|
|
1382
|
-
return keyed;
|
|
1383
|
-
} else {
|
|
1384
|
-
return loadedTextures;
|
|
1385
|
-
}
|
|
1386
|
-
}, [input, loadedTextures, cachedResult]);
|
|
1387
1146
|
React.useEffect(() => {
|
|
1388
1147
|
if (!cache) return;
|
|
1389
1148
|
const urlTextureMap = [];
|
|
1390
|
-
if (typeof
|
|
1391
|
-
urlTextureMap.push([
|
|
1392
|
-
} else if (Array.isArray(
|
|
1149
|
+
if (typeof stableInput === "string") {
|
|
1150
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1151
|
+
} else if (Array.isArray(stableInput)) {
|
|
1393
1152
|
const textureArray = mappedTextures;
|
|
1394
|
-
|
|
1395
|
-
} else if (IsObject(
|
|
1153
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1154
|
+
} else if (IsObject(stableInput)) {
|
|
1396
1155
|
const textureRecord = mappedTextures;
|
|
1397
|
-
for (const key in
|
|
1398
|
-
const url =
|
|
1156
|
+
for (const key in stableInput) {
|
|
1157
|
+
const url = stableInput[key];
|
|
1399
1158
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1400
1159
|
}
|
|
1401
1160
|
}
|
|
@@ -1424,7 +1183,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1424
1183
|
}
|
|
1425
1184
|
return { _textureRefs: refs };
|
|
1426
1185
|
});
|
|
1427
|
-
}, [cache,
|
|
1186
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1428
1187
|
return mappedTextures;
|
|
1429
1188
|
}
|
|
1430
1189
|
useTexture.preload = (url) => useLoader.preload(webgpu.TextureLoader, url);
|
|
@@ -1585,7 +1344,7 @@ function useEnvironment({
|
|
|
1585
1344
|
texture = texture.renderTarget?.texture;
|
|
1586
1345
|
}
|
|
1587
1346
|
texture.mapping = isCubemap ? webgpu.CubeReflectionMapping : webgpu.EquirectangularReflectionMapping;
|
|
1588
|
-
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
1347
|
+
texture.colorSpace = colorSpace ?? (isCubemap && extension !== "hdr-cube" ? "srgb" : "srgb-linear");
|
|
1589
1348
|
return texture;
|
|
1590
1349
|
}
|
|
1591
1350
|
const preloadDefaultOptions = {
|
|
@@ -1638,22 +1397,15 @@ function getExtension(files) {
|
|
|
1638
1397
|
const isCubemap = isArray(files) && files.length === 6;
|
|
1639
1398
|
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
1640
1399
|
const firstEntry = isArray(files) ? files[0] : files;
|
|
1641
|
-
const
|
|
1400
|
+
const firstExtension = firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
1401
|
+
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;
|
|
1642
1402
|
return { extension, isCubemap, isGainmap };
|
|
1643
1403
|
}
|
|
1644
1404
|
function getLoader(extension) {
|
|
1645
|
-
const loader = extension === "cube" ? webgpu.CubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
|
|
1405
|
+
const loader = extension === "cube" ? webgpu.CubeTextureLoader : extension === "hdr-cube" ? HDRCubeTextureLoader_js.HDRCubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
|
|
1646
1406
|
return loader;
|
|
1647
1407
|
}
|
|
1648
1408
|
|
|
1649
|
-
function useStore() {
|
|
1650
|
-
const store = React.useContext(context);
|
|
1651
|
-
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1652
|
-
return store;
|
|
1653
|
-
}
|
|
1654
|
-
function useThree$1(selector = (state) => state, equalityFn) {
|
|
1655
|
-
return useStore()(selector, equalityFn);
|
|
1656
|
-
}
|
|
1657
1409
|
function useInstanceHandle(ref) {
|
|
1658
1410
|
const instance = React.useRef(null);
|
|
1659
1411
|
React.useImperativeHandle(instance, () => ref.current.__r3f, [ref]);
|
|
@@ -1693,22 +1445,28 @@ function addTail(callback) {
|
|
|
1693
1445
|
return scheduler.getScheduler().onIdle(callback);
|
|
1694
1446
|
}
|
|
1695
1447
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1696
|
-
|
|
1448
|
+
const rootId = state?.internal?.rootId;
|
|
1449
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1450
|
+
if (rootId) scheduler$1.invalidateRoot(rootId, frames, stackFrames);
|
|
1451
|
+
else scheduler$1.invalidate(frames, stackFrames);
|
|
1697
1452
|
}
|
|
1698
|
-
function advance(timestamp) {
|
|
1699
|
-
|
|
1453
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1454
|
+
const rootId = state?.internal?.rootId;
|
|
1455
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1456
|
+
if (rootId) scheduler$1.stepRoot(rootId, timestamp);
|
|
1457
|
+
else scheduler$1.step(timestamp);
|
|
1700
1458
|
}
|
|
1701
1459
|
|
|
1702
|
-
const version = "10.0.0-alpha.
|
|
1460
|
+
const version = "10.0.0-alpha.5";
|
|
1703
1461
|
const packageData = {
|
|
1704
1462
|
version: version};
|
|
1705
1463
|
|
|
1706
1464
|
function Xb(Tt) {
|
|
1707
1465
|
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
1708
1466
|
}
|
|
1709
|
-
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
1467
|
+
var Rm = { exports: {} }, Og = { exports: {} }, _b$1;
|
|
1710
1468
|
function Kb() {
|
|
1711
|
-
return _b || (_b = 1, (function(Tt) {
|
|
1469
|
+
return _b$1 || (_b$1 = 1, (function(Tt) {
|
|
1712
1470
|
Tt.exports = function(m) {
|
|
1713
1471
|
function Yn(t, r, a, l) {
|
|
1714
1472
|
return new uc(t, r, a, l);
|
|
@@ -13558,7 +13316,10 @@ function extend(objects) {
|
|
|
13558
13316
|
catalogue[Component] = objects;
|
|
13559
13317
|
return Component;
|
|
13560
13318
|
} else {
|
|
13561
|
-
|
|
13319
|
+
for (const name in objects) {
|
|
13320
|
+
const object = objects[name];
|
|
13321
|
+
if (isConstructor(object)) catalogue[name] = object;
|
|
13322
|
+
}
|
|
13562
13323
|
}
|
|
13563
13324
|
}
|
|
13564
13325
|
function validateInstance(type, props) {
|
|
@@ -13906,7 +13667,7 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13906
13667
|
getRootHostContext: () => NO_CONTEXT,
|
|
13907
13668
|
getChildHostContext: () => NO_CONTEXT,
|
|
13908
13669
|
commitUpdate(instance, type, oldProps, newProps, fiber) {
|
|
13909
|
-
validateInstance(type, newProps);
|
|
13670
|
+
validateInstance(instance.type, newProps);
|
|
13910
13671
|
let reconstruct = false;
|
|
13911
13672
|
if (instance.type === "primitive" && oldProps.object !== newProps.object) reconstruct = true;
|
|
13912
13673
|
else if (newProps.args?.length !== oldProps.args?.length) reconstruct = true;
|
|
@@ -13933,8 +13694,8 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
13933
13694
|
for (const prop in instance.props) {
|
|
13934
13695
|
const value = instance.props[prop];
|
|
13935
13696
|
if (isFromRef(value)) {
|
|
13936
|
-
const ref = value
|
|
13937
|
-
if (ref.current != null) resolved[prop] = ref.current;
|
|
13697
|
+
const { [FROM_REF]: ref, transform } = value;
|
|
13698
|
+
if (ref.current != null) resolved[prop] = transform ? transform(ref.current) : ref.current;
|
|
13938
13699
|
}
|
|
13939
13700
|
}
|
|
13940
13701
|
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
@@ -14078,6 +13839,335 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14078
13839
|
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
14079
13840
|
});
|
|
14080
13841
|
|
|
13842
|
+
const INTERNAL_LIB_MARKERS = ["zustand", "setState", "Object.assign"];
|
|
13843
|
+
function isInternalRendererAccess(stack, callerDepth = 2) {
|
|
13844
|
+
if (!stack) return false;
|
|
13845
|
+
const caller = stack.split("\n")[callerDepth] ?? "";
|
|
13846
|
+
return INTERNAL_LIB_MARKERS.some((m) => caller.includes(m));
|
|
13847
|
+
}
|
|
13848
|
+
|
|
13849
|
+
const createStore = (invalidate, advance) => {
|
|
13850
|
+
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
13851
|
+
const position = new webgpu.Vector3();
|
|
13852
|
+
const defaultTarget = new webgpu.Vector3();
|
|
13853
|
+
const tempTarget = new webgpu.Vector3();
|
|
13854
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
13855
|
+
const { width, height, top, left } = size;
|
|
13856
|
+
const aspect = width / height;
|
|
13857
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
13858
|
+
else tempTarget.set(...target);
|
|
13859
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
13860
|
+
if (isOrthographicCamera(camera)) {
|
|
13861
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
13862
|
+
} else {
|
|
13863
|
+
const fov = camera.fov * Math.PI / 180;
|
|
13864
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
13865
|
+
const w = h * (width / height);
|
|
13866
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
13867
|
+
}
|
|
13868
|
+
}
|
|
13869
|
+
let performanceTimeout = void 0;
|
|
13870
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
13871
|
+
const pointer = new webgpu.Vector2();
|
|
13872
|
+
const rootState = {
|
|
13873
|
+
set,
|
|
13874
|
+
get,
|
|
13875
|
+
// Mock objects that have to be configured
|
|
13876
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
13877
|
+
primaryStore: null,
|
|
13878
|
+
gl: null,
|
|
13879
|
+
renderer: null,
|
|
13880
|
+
camera: null,
|
|
13881
|
+
frustum: new webgpu.Frustum(),
|
|
13882
|
+
autoUpdateFrustum: true,
|
|
13883
|
+
raycaster: null,
|
|
13884
|
+
events: {
|
|
13885
|
+
priority: 1,
|
|
13886
|
+
enabled: true,
|
|
13887
|
+
connected: false,
|
|
13888
|
+
frameTimedRaycasts: true,
|
|
13889
|
+
alwaysFireOnScroll: true,
|
|
13890
|
+
updateOnFrame: false
|
|
13891
|
+
},
|
|
13892
|
+
scene: null,
|
|
13893
|
+
rootScene: null,
|
|
13894
|
+
xr: null,
|
|
13895
|
+
inspector: null,
|
|
13896
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
13897
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
13898
|
+
textureColorSpace: webgpu.SRGBColorSpace,
|
|
13899
|
+
isLegacy: false,
|
|
13900
|
+
webGPUSupported: false,
|
|
13901
|
+
isNative: false,
|
|
13902
|
+
controls: null,
|
|
13903
|
+
pointer,
|
|
13904
|
+
mouse: pointer,
|
|
13905
|
+
frameloop: "always",
|
|
13906
|
+
onPointerMissed: void 0,
|
|
13907
|
+
onDragOverMissed: void 0,
|
|
13908
|
+
onDropMissed: void 0,
|
|
13909
|
+
performance: {
|
|
13910
|
+
current: 1,
|
|
13911
|
+
min: 0.5,
|
|
13912
|
+
max: 1,
|
|
13913
|
+
debounce: 200,
|
|
13914
|
+
regress: () => {
|
|
13915
|
+
const state2 = get();
|
|
13916
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
13917
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
13918
|
+
performanceTimeout = setTimeout(
|
|
13919
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
13920
|
+
state2.performance.debounce
|
|
13921
|
+
);
|
|
13922
|
+
}
|
|
13923
|
+
},
|
|
13924
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
13925
|
+
viewport: {
|
|
13926
|
+
initialDpr: 0,
|
|
13927
|
+
dpr: 0,
|
|
13928
|
+
width: 0,
|
|
13929
|
+
height: 0,
|
|
13930
|
+
top: 0,
|
|
13931
|
+
left: 0,
|
|
13932
|
+
aspect: 0,
|
|
13933
|
+
distance: 0,
|
|
13934
|
+
factor: 0,
|
|
13935
|
+
getCurrentViewport
|
|
13936
|
+
},
|
|
13937
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
13938
|
+
setSize: (width, height, top, left) => {
|
|
13939
|
+
const state2 = get();
|
|
13940
|
+
if (width === void 0) {
|
|
13941
|
+
set({ _sizeImperative: false });
|
|
13942
|
+
if (state2._sizeProps) {
|
|
13943
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
13944
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
13945
|
+
const currentSize = state2.size;
|
|
13946
|
+
const newSize = {
|
|
13947
|
+
width: propW ?? currentSize.width,
|
|
13948
|
+
height: propH ?? currentSize.height,
|
|
13949
|
+
top: currentSize.top,
|
|
13950
|
+
left: currentSize.left
|
|
13951
|
+
};
|
|
13952
|
+
set((s) => ({
|
|
13953
|
+
size: newSize,
|
|
13954
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
13955
|
+
}));
|
|
13956
|
+
get().invalidate();
|
|
13957
|
+
}
|
|
13958
|
+
}
|
|
13959
|
+
return;
|
|
13960
|
+
}
|
|
13961
|
+
const w = width;
|
|
13962
|
+
const h = height ?? width;
|
|
13963
|
+
const t = top ?? state2.size.top;
|
|
13964
|
+
const l = left ?? state2.size.left;
|
|
13965
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
13966
|
+
set((s) => ({
|
|
13967
|
+
size,
|
|
13968
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
13969
|
+
_sizeImperative: true
|
|
13970
|
+
}));
|
|
13971
|
+
get().invalidate();
|
|
13972
|
+
},
|
|
13973
|
+
setDpr: (dpr) => set((state2) => {
|
|
13974
|
+
const resolved = calculateDpr(dpr);
|
|
13975
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
13976
|
+
}),
|
|
13977
|
+
setFrameloop: (frameloop = "always") => {
|
|
13978
|
+
const rootId = get().internal.rootId;
|
|
13979
|
+
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
13980
|
+
set(() => ({ frameloop }));
|
|
13981
|
+
},
|
|
13982
|
+
setError: (error) => set(() => ({ error })),
|
|
13983
|
+
error: null,
|
|
13984
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
13985
|
+
uniforms: {},
|
|
13986
|
+
nodes: {},
|
|
13987
|
+
buffers: {},
|
|
13988
|
+
gpuStorage: {},
|
|
13989
|
+
textures: /* @__PURE__ */ new Map(),
|
|
13990
|
+
_textureRefs: /* @__PURE__ */ new Map(),
|
|
13991
|
+
renderPipeline: null,
|
|
13992
|
+
passes: {},
|
|
13993
|
+
_hmrVersion: 0,
|
|
13994
|
+
_sizeImperative: false,
|
|
13995
|
+
_sizeProps: null,
|
|
13996
|
+
previousRoot: void 0,
|
|
13997
|
+
internal: {
|
|
13998
|
+
// Events
|
|
13999
|
+
interaction: [],
|
|
14000
|
+
subscribers: [],
|
|
14001
|
+
// Per-pointer state (new unified structure)
|
|
14002
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
14003
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
14004
|
+
lastEvent: React__namespace.createRef(),
|
|
14005
|
+
// Deprecated but kept for backwards compatibility
|
|
14006
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
14007
|
+
initialClick: [0, 0],
|
|
14008
|
+
initialHits: [],
|
|
14009
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
14010
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
14011
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
14012
|
+
// Occlusion system (WebGPU only)
|
|
14013
|
+
occlusionEnabled: false,
|
|
14014
|
+
occlusionObserver: null,
|
|
14015
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
14016
|
+
helperGroup: null,
|
|
14017
|
+
// Updates
|
|
14018
|
+
active: false,
|
|
14019
|
+
frames: 0,
|
|
14020
|
+
priority: 0,
|
|
14021
|
+
subscribe: (ref, priority, store) => {
|
|
14022
|
+
const internal = get().internal;
|
|
14023
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
14024
|
+
internal.subscribers.push({ ref, priority, store });
|
|
14025
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
14026
|
+
return () => {
|
|
14027
|
+
const internal2 = get().internal;
|
|
14028
|
+
if (internal2?.subscribers) {
|
|
14029
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
14030
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
14031
|
+
}
|
|
14032
|
+
};
|
|
14033
|
+
},
|
|
14034
|
+
// Renderer Storage (single source of truth)
|
|
14035
|
+
actualRenderer: null,
|
|
14036
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
14037
|
+
scheduler: null,
|
|
14038
|
+
// Replaces the default render call when set (see setRenderOverride)
|
|
14039
|
+
renderOverride: null
|
|
14040
|
+
}
|
|
14041
|
+
};
|
|
14042
|
+
return rootState;
|
|
14043
|
+
});
|
|
14044
|
+
const state = rootStore.getState();
|
|
14045
|
+
Object.defineProperty(state, "gl", {
|
|
14046
|
+
get() {
|
|
14047
|
+
const currentState = rootStore.getState();
|
|
14048
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
14049
|
+
const stack = new Error().stack || "";
|
|
14050
|
+
if (!isInternalRendererAccess(stack)) {
|
|
14051
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
14052
|
+
notifyDepreciated({
|
|
14053
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
14054
|
+
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
|
|
14055
|
+
});
|
|
14056
|
+
}
|
|
14057
|
+
}
|
|
14058
|
+
return currentState.internal.actualRenderer;
|
|
14059
|
+
},
|
|
14060
|
+
set(value) {
|
|
14061
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14062
|
+
},
|
|
14063
|
+
enumerable: true,
|
|
14064
|
+
configurable: true
|
|
14065
|
+
});
|
|
14066
|
+
Object.defineProperty(state, "renderer", {
|
|
14067
|
+
get() {
|
|
14068
|
+
return rootStore.getState().internal.actualRenderer;
|
|
14069
|
+
},
|
|
14070
|
+
set(value) {
|
|
14071
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
14072
|
+
},
|
|
14073
|
+
enumerable: true,
|
|
14074
|
+
configurable: true
|
|
14075
|
+
});
|
|
14076
|
+
let oldScene = state.scene;
|
|
14077
|
+
rootStore.subscribe(() => {
|
|
14078
|
+
const currentState = rootStore.getState();
|
|
14079
|
+
const { scene, rootScene, set } = currentState;
|
|
14080
|
+
if (scene !== oldScene) {
|
|
14081
|
+
oldScene = scene;
|
|
14082
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
14083
|
+
set({ rootScene: scene });
|
|
14084
|
+
}
|
|
14085
|
+
}
|
|
14086
|
+
});
|
|
14087
|
+
let oldSize = state.size;
|
|
14088
|
+
let oldDpr = state.viewport.dpr;
|
|
14089
|
+
let oldCamera = state.camera;
|
|
14090
|
+
rootStore.subscribe(() => {
|
|
14091
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
14092
|
+
const actualRenderer = internal.actualRenderer;
|
|
14093
|
+
const canvasTarget = internal.canvasTarget;
|
|
14094
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
14095
|
+
oldSize = size;
|
|
14096
|
+
oldDpr = viewport.dpr;
|
|
14097
|
+
updateCamera(camera, size);
|
|
14098
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
14099
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
14100
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
14101
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
14102
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
14103
|
+
}
|
|
14104
|
+
if (camera !== oldCamera) {
|
|
14105
|
+
oldCamera = camera;
|
|
14106
|
+
const { rootScene } = rootStore.getState();
|
|
14107
|
+
if (camera && rootScene && !camera.parent) {
|
|
14108
|
+
rootScene.add(camera);
|
|
14109
|
+
}
|
|
14110
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
14111
|
+
const currentState = rootStore.getState();
|
|
14112
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
14113
|
+
updateFrustum(camera, currentState.frustum);
|
|
14114
|
+
}
|
|
14115
|
+
}
|
|
14116
|
+
});
|
|
14117
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
14118
|
+
return rootStore;
|
|
14119
|
+
};
|
|
14120
|
+
|
|
14121
|
+
const R3F_EXTENSIONS = Symbol.for("@react-three/fiber.extensions");
|
|
14122
|
+
function getRegistry() {
|
|
14123
|
+
return globalThis[R3F_EXTENSIONS] ?? (globalThis[R3F_EXTENSIONS] = {
|
|
14124
|
+
extensions: /* @__PURE__ */ new Map(),
|
|
14125
|
+
roots: /* @__PURE__ */ new Set(),
|
|
14126
|
+
applied: /* @__PURE__ */ new WeakMap()
|
|
14127
|
+
});
|
|
14128
|
+
}
|
|
14129
|
+
function setupRoot(registry, store, extension) {
|
|
14130
|
+
let applied = registry.applied.get(store);
|
|
14131
|
+
if (!applied) registry.applied.set(store, applied = /* @__PURE__ */ new Map());
|
|
14132
|
+
if (applied.has(extension.name)) return;
|
|
14133
|
+
applied.set(extension.name, extension);
|
|
14134
|
+
const patch = extension.setup?.(store);
|
|
14135
|
+
if (patch) store.setState(patch);
|
|
14136
|
+
}
|
|
14137
|
+
function registerRootExtension(extension) {
|
|
14138
|
+
const registry = getRegistry();
|
|
14139
|
+
registry.extensions.set(extension.name, extension);
|
|
14140
|
+
for (const store of registry.roots) setupRoot(registry, store, extension);
|
|
14141
|
+
return () => {
|
|
14142
|
+
if (registry.extensions.get(extension.name) === extension) registry.extensions.delete(extension.name);
|
|
14143
|
+
};
|
|
14144
|
+
}
|
|
14145
|
+
function setRenderOverride(store, render) {
|
|
14146
|
+
store.getState().internal.renderOverride = render;
|
|
14147
|
+
}
|
|
14148
|
+
function attachRootExtensions(store) {
|
|
14149
|
+
const registry = getRegistry();
|
|
14150
|
+
registry.roots.add(store);
|
|
14151
|
+
for (const extension of registry.extensions.values()) setupRoot(registry, store, extension);
|
|
14152
|
+
}
|
|
14153
|
+
function current(registry, setUpBy) {
|
|
14154
|
+
return registry.extensions.get(setUpBy.name) ?? setUpBy;
|
|
14155
|
+
}
|
|
14156
|
+
function detachRootExtensions(store) {
|
|
14157
|
+
const registry = getRegistry();
|
|
14158
|
+
if (!registry.roots.delete(store)) return;
|
|
14159
|
+
const applied = registry.applied.get(store);
|
|
14160
|
+
registry.applied.delete(store);
|
|
14161
|
+
if (!applied) return;
|
|
14162
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).dispose?.(store);
|
|
14163
|
+
}
|
|
14164
|
+
function notifyRootExtensionsHmr(store) {
|
|
14165
|
+
const registry = getRegistry();
|
|
14166
|
+
const applied = registry.applied.get(store);
|
|
14167
|
+
if (!applied) return;
|
|
14168
|
+
for (const setUpBy of applied.values()) current(registry, setUpBy).hmr?.(store);
|
|
14169
|
+
}
|
|
14170
|
+
|
|
14081
14171
|
const isRenderer = (def) => !!def?.render;
|
|
14082
14172
|
const _roots = /* @__PURE__ */ new Map();
|
|
14083
14173
|
const shallowLoose = { objects: "shallow", strict: false };
|
|
@@ -14215,9 +14305,8 @@ function createRoot(canvas) {
|
|
|
14215
14305
|
if (!renderer.hasInitialized?.()) {
|
|
14216
14306
|
const size2 = computeInitialSize(canvas, propsSize);
|
|
14217
14307
|
if (size2.width > 0 && size2.height > 0) {
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
canvas.height = size2.height * pixelRatio;
|
|
14308
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14309
|
+
renderer.setSize(size2.width, size2.height, false);
|
|
14221
14310
|
}
|
|
14222
14311
|
await renderer.init();
|
|
14223
14312
|
}
|
|
@@ -14226,7 +14315,7 @@ function createRoot(canvas) {
|
|
|
14226
14315
|
state.internal.actualRenderer = renderer;
|
|
14227
14316
|
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14228
14317
|
if (canvasId && !state.internal.isSecondary) {
|
|
14229
|
-
const canvasTarget =
|
|
14318
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14230
14319
|
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14231
14320
|
state.set((prev) => ({
|
|
14232
14321
|
internal: {
|
|
@@ -14340,7 +14429,7 @@ function createRoot(canvas) {
|
|
|
14340
14429
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14341
14430
|
const state2 = store.getState();
|
|
14342
14431
|
if (state2.frameloop === "never") return;
|
|
14343
|
-
advance(timestamp);
|
|
14432
|
+
advance(timestamp, true, state2);
|
|
14344
14433
|
};
|
|
14345
14434
|
const actualRenderer = state.internal.actualRenderer;
|
|
14346
14435
|
const handleSessionChange = () => {
|
|
@@ -14348,7 +14437,7 @@ function createRoot(canvas) {
|
|
|
14348
14437
|
const renderer2 = state2.internal.actualRenderer;
|
|
14349
14438
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14350
14439
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14351
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14440
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14352
14441
|
};
|
|
14353
14442
|
const xr = {
|
|
14354
14443
|
connect() {
|
|
@@ -14430,14 +14519,23 @@ function createRoot(canvas) {
|
|
|
14430
14519
|
const newRootId = canvasId || scheduler$1.generateRootId();
|
|
14431
14520
|
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
14432
14521
|
getState: () => store.getState(),
|
|
14433
|
-
onError: (err) => store.getState().setError(err)
|
|
14522
|
+
onError: (err) => store.getState().setError(err),
|
|
14523
|
+
frameloop: store.getState().frameloop,
|
|
14524
|
+
before: schedulerConfig?.before,
|
|
14525
|
+
after: schedulerConfig?.after,
|
|
14526
|
+
order: schedulerConfig?.order
|
|
14434
14527
|
});
|
|
14435
14528
|
const unregisterCanvasTarget = scheduler$1.register(
|
|
14436
14529
|
() => {
|
|
14437
14530
|
const state2 = store.getState();
|
|
14438
|
-
|
|
14531
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14532
|
+
if (canvasTarget) {
|
|
14439
14533
|
const renderer2 = state2.internal.actualRenderer;
|
|
14440
|
-
renderer2.setCanvasTarget(
|
|
14534
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14535
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14536
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14537
|
+
renderer2.backend?.updateSize?.();
|
|
14538
|
+
}
|
|
14441
14539
|
}
|
|
14442
14540
|
},
|
|
14443
14541
|
{
|
|
@@ -14493,7 +14591,8 @@ function createRoot(canvas) {
|
|
|
14493
14591
|
const userHandlesRender = scheduler$1.hasUserJobsInPhase("render", newRootId);
|
|
14494
14592
|
if (userHandlesRender || state2.internal.priority) return;
|
|
14495
14593
|
try {
|
|
14496
|
-
|
|
14594
|
+
const renderOverride = state2.internal.renderOverride;
|
|
14595
|
+
if (renderOverride) renderOverride();
|
|
14497
14596
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
14498
14597
|
} catch (error) {
|
|
14499
14598
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -14506,8 +14605,7 @@ function createRoot(canvas) {
|
|
|
14506
14605
|
phase: "render",
|
|
14507
14606
|
system: true,
|
|
14508
14607
|
// Internal flag: this is a system job, not user-controlled
|
|
14509
|
-
//
|
|
14510
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14608
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14511
14609
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14512
14610
|
}
|
|
14513
14611
|
);
|
|
@@ -14526,8 +14624,22 @@ function createRoot(canvas) {
|
|
|
14526
14624
|
scheduler: scheduler$1
|
|
14527
14625
|
}
|
|
14528
14626
|
}));
|
|
14627
|
+
} else {
|
|
14628
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14629
|
+
if (constraintsChanged) {
|
|
14630
|
+
scheduler$1.setRootConstraints(rootId, {
|
|
14631
|
+
before: schedulerConfig?.before,
|
|
14632
|
+
after: schedulerConfig?.after
|
|
14633
|
+
});
|
|
14634
|
+
}
|
|
14635
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14636
|
+
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14637
|
+
}
|
|
14529
14638
|
}
|
|
14530
|
-
|
|
14639
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14640
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14641
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14642
|
+
attachRootExtensions(store);
|
|
14531
14643
|
onCreated = onCreatedCallback;
|
|
14532
14644
|
configured = true;
|
|
14533
14645
|
resolve();
|
|
@@ -14569,18 +14681,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14569
14681
|
const fiber = root?.fiber;
|
|
14570
14682
|
if (fiber) {
|
|
14571
14683
|
const state = root?.store.getState();
|
|
14572
|
-
if (state)
|
|
14684
|
+
if (state) {
|
|
14685
|
+
state.internal.active = false;
|
|
14686
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14687
|
+
if (unregisterRoot) {
|
|
14688
|
+
unregisterRoot();
|
|
14689
|
+
state.internal.unregisterRoot = void 0;
|
|
14690
|
+
}
|
|
14691
|
+
}
|
|
14573
14692
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14693
|
+
if (root?.store) detachRootExtensions(root.store);
|
|
14574
14694
|
if (state) {
|
|
14575
14695
|
setTimeout(() => {
|
|
14576
14696
|
try {
|
|
14577
14697
|
const renderer = state.internal.actualRenderer;
|
|
14578
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14579
|
-
if (unregisterRoot) unregisterRoot();
|
|
14580
14698
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14581
14699
|
if (unregisterPrimary) unregisterPrimary();
|
|
14582
14700
|
const canvasTarget = state.internal.canvasTarget;
|
|
14583
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14701
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14584
14702
|
state.events.disconnect?.();
|
|
14585
14703
|
cleanupHelperGroup(root.store);
|
|
14586
14704
|
if (state.isLegacy && renderer) {
|
|
@@ -14650,11 +14768,24 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14650
14768
|
}
|
|
14651
14769
|
};
|
|
14652
14770
|
}, [portalScene, container, injectScene]);
|
|
14771
|
+
const lastRootState = React.useRef(null);
|
|
14653
14772
|
const inject = useMutableCallback((rootState, injectState) => {
|
|
14773
|
+
const followed = {};
|
|
14774
|
+
const lastRoot = lastRootState.current;
|
|
14775
|
+
if (lastRoot) {
|
|
14776
|
+
for (const key in rootState) {
|
|
14777
|
+
const field = key;
|
|
14778
|
+
const changed = rootState[field] !== lastRoot[field];
|
|
14779
|
+
const inherited = !(key in rest) && injectState[field] === lastRoot[field];
|
|
14780
|
+
if (changed && inherited) followed[field] = rootState[field];
|
|
14781
|
+
}
|
|
14782
|
+
}
|
|
14783
|
+
lastRootState.current = rootState;
|
|
14654
14784
|
const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
|
|
14655
14785
|
let viewport = void 0;
|
|
14656
|
-
|
|
14657
|
-
|
|
14786
|
+
const portalCamera = followed.camera ?? injectState.camera;
|
|
14787
|
+
if (portalCamera && (size || injectState.size)) {
|
|
14788
|
+
const camera = portalCamera;
|
|
14658
14789
|
viewport = rootState.viewport.getCurrentViewport(camera, new webgpu.Vector3(), resolvedSize);
|
|
14659
14790
|
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14660
14791
|
}
|
|
@@ -14663,6 +14794,7 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
14663
14794
|
// The intersect consists of the previous root state
|
|
14664
14795
|
...rootState,
|
|
14665
14796
|
...injectState,
|
|
14797
|
+
...followed,
|
|
14666
14798
|
// Portals have their own scene - always a real THREE.Scene (injected if needed)
|
|
14667
14799
|
scene: portalScene,
|
|
14668
14800
|
// rootScene always points to the actual THREE.Scene, even inside portals
|
|
@@ -14721,16 +14853,11 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14721
14853
|
const oldbg = target.background;
|
|
14722
14854
|
const oldenv = target.environment;
|
|
14723
14855
|
const oldSceneProps = {
|
|
14724
|
-
// @ts-ignore
|
|
14725
14856
|
backgroundBlurriness: target.backgroundBlurriness,
|
|
14726
|
-
// @ts-ignore
|
|
14727
14857
|
backgroundIntensity: target.backgroundIntensity,
|
|
14728
|
-
|
|
14729
|
-
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
14730
|
-
// @ts-ignore
|
|
14858
|
+
backgroundRotation: target.backgroundRotation.clone(),
|
|
14731
14859
|
environmentIntensity: target.environmentIntensity,
|
|
14732
|
-
|
|
14733
|
-
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
14860
|
+
environmentRotation: target.environmentRotation.clone()
|
|
14734
14861
|
};
|
|
14735
14862
|
if (background !== "only") target.environment = texture;
|
|
14736
14863
|
if (background) target.background = texture;
|
|
@@ -14937,151 +15064,22 @@ function parseBackground(background) {
|
|
|
14937
15064
|
return { color: background, background: true };
|
|
14938
15065
|
}
|
|
14939
15066
|
if (background.isColor) {
|
|
14940
|
-
return { color: background, background: true };
|
|
14941
|
-
}
|
|
14942
|
-
return null;
|
|
14943
|
-
}
|
|
14944
|
-
|
|
14945
|
-
function parseRendererConfig(rendererProp) {
|
|
14946
|
-
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
14947
|
-
if (isRendererConfig) {
|
|
14948
|
-
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
14949
|
-
return {
|
|
14950
|
-
primaryCanvas: pc,
|
|
14951
|
-
scheduler: sc,
|
|
14952
|
-
renderer: Object.keys(rest).length > 0 ? rest : rendererProp
|
|
14953
|
-
};
|
|
14954
|
-
}
|
|
14955
|
-
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
14956
|
-
}
|
|
14957
|
-
|
|
14958
|
-
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
14959
|
-
const ROOT_SCOPE = "";
|
|
14960
|
-
const registries = /* @__PURE__ */ new WeakMap();
|
|
14961
|
-
function getKindRegistry(store, kind) {
|
|
14962
|
-
let registry = registries.get(store);
|
|
14963
|
-
if (!registry) {
|
|
14964
|
-
registry = {
|
|
14965
|
-
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14966
|
-
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14967
|
-
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
14968
|
-
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
14969
|
-
};
|
|
14970
|
-
registries.set(store, registry);
|
|
14971
|
-
}
|
|
14972
|
-
return registry[kind];
|
|
14973
|
-
}
|
|
14974
|
-
function resolvePrimary$1(store) {
|
|
14975
|
-
return store.getState().primaryStore ?? store;
|
|
14976
|
-
}
|
|
14977
|
-
function isScopeValid(store, kind, scopeKey) {
|
|
14978
|
-
return getKindRegistry(store, kind).valid.has(scopeKey);
|
|
14979
|
-
}
|
|
14980
|
-
function peekStaged(store, kind, scopeKey) {
|
|
14981
|
-
return getKindRegistry(store, kind).staged.get(scopeKey);
|
|
14982
|
-
}
|
|
14983
|
-
function stageEntries(store, kind, scopeKey, entries) {
|
|
14984
|
-
const { staged } = getKindRegistry(store, kind);
|
|
14985
|
-
const current = staged.get(scopeKey);
|
|
14986
|
-
if (current) Object.assign(current, entries);
|
|
14987
|
-
else staged.set(scopeKey, { ...entries });
|
|
14988
|
-
}
|
|
14989
|
-
function readCommittedScope(map, scopeKey, isLeaf) {
|
|
14990
|
-
if (scopeKey === ROOT_SCOPE) {
|
|
14991
|
-
const leaves = {};
|
|
14992
|
-
for (const [key, value] of Object.entries(map)) if (isLeaf(value)) leaves[key] = value;
|
|
14993
|
-
return leaves;
|
|
14994
|
-
}
|
|
14995
|
-
const scopeData = map[scopeKey];
|
|
14996
|
-
if (scopeData && typeof scopeData === "object" && !isLeaf(scopeData)) return scopeData;
|
|
14997
|
-
return {};
|
|
14998
|
-
}
|
|
14999
|
-
function withStagedOverlay(store, kind, committed) {
|
|
15000
|
-
const { staged } = getKindRegistry(store, kind);
|
|
15001
|
-
if (staged.size === 0) return committed;
|
|
15002
|
-
const view = { ...committed };
|
|
15003
|
-
for (const [scopeKey, entries] of staged) {
|
|
15004
|
-
if (scopeKey === ROOT_SCOPE) Object.assign(view, entries);
|
|
15005
|
-
else view[scopeKey] = { ...view[scopeKey], ...entries };
|
|
15006
|
-
}
|
|
15007
|
-
return view;
|
|
15008
|
-
}
|
|
15009
|
-
function flushStagedScope(store, kind, scopeKey, isLeaf) {
|
|
15010
|
-
const registry = getKindRegistry(store, kind);
|
|
15011
|
-
const staged = registry.staged.get(scopeKey);
|
|
15012
|
-
if (!staged) return;
|
|
15013
|
-
registry.staged.delete(scopeKey);
|
|
15014
|
-
const replace = !registry.valid.has(scopeKey);
|
|
15015
|
-
store.setState((state) => {
|
|
15016
|
-
const map = state[kind];
|
|
15017
|
-
if (scopeKey === ROOT_SCOPE) {
|
|
15018
|
-
if (!replace) return { [kind]: { ...map, ...staged } };
|
|
15019
|
-
const next = {};
|
|
15020
|
-
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15021
|
-
return { [kind]: { ...next, ...staged } };
|
|
15022
|
-
}
|
|
15023
|
-
const current = replace ? {} : map[scopeKey] ?? {};
|
|
15024
|
-
return { [kind]: { ...map, [scopeKey]: { ...current, ...staged } } };
|
|
15025
|
-
});
|
|
15026
|
-
registry.valid.add(scopeKey);
|
|
15027
|
-
}
|
|
15028
|
-
function invalidateResource(store, kind, scopeKey) {
|
|
15029
|
-
const registry = getKindRegistry(store, kind);
|
|
15030
|
-
if (scopeKey === void 0) {
|
|
15031
|
-
registry.valid.clear();
|
|
15032
|
-
registry.staged.clear();
|
|
15033
|
-
} else {
|
|
15034
|
-
registry.valid.delete(scopeKey);
|
|
15035
|
-
registry.staged.delete(scopeKey);
|
|
15036
|
-
}
|
|
15037
|
-
}
|
|
15038
|
-
function rebuildResource(store, kind, userScope) {
|
|
15039
|
-
const primary = resolvePrimary$1(store);
|
|
15040
|
-
invalidateResource(primary, kind, userScope === "root" ? ROOT_SCOPE : userScope);
|
|
15041
|
-
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
15042
|
-
}
|
|
15043
|
-
function invalidateAllResources(store) {
|
|
15044
|
-
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
15045
|
-
}
|
|
15046
|
-
function removeResourceEntries(store, kind, names, scope, isLeaf) {
|
|
15047
|
-
const staged = peekStaged(store, kind, scope ?? ROOT_SCOPE);
|
|
15048
|
-
if (staged) for (const name of names) delete staged[name];
|
|
15049
|
-
store.setState((state) => {
|
|
15050
|
-
const map = state[kind];
|
|
15051
|
-
if (scope) {
|
|
15052
|
-
const currentScope = { ...map[scope] };
|
|
15053
|
-
for (const name of names) delete currentScope[name];
|
|
15054
|
-
return { [kind]: { ...map, [scope]: currentScope } };
|
|
15055
|
-
}
|
|
15056
|
-
const next = { ...map };
|
|
15057
|
-
for (const name of names) if (isLeaf(next[name])) delete next[name];
|
|
15058
|
-
return { [kind]: next };
|
|
15059
|
-
});
|
|
15060
|
-
}
|
|
15061
|
-
function clearResourceEntries(store, kind, scope, isLeaf) {
|
|
15062
|
-
const registry = getKindRegistry(store, kind);
|
|
15063
|
-
if (scope && scope !== "root") registry.staged.delete(scope);
|
|
15064
|
-
else if (scope === "root") registry.staged.delete(ROOT_SCOPE);
|
|
15065
|
-
else registry.staged.clear();
|
|
15066
|
-
store.setState((state) => {
|
|
15067
|
-
const map = state[kind];
|
|
15068
|
-
if (scope && scope !== "root") {
|
|
15069
|
-
const { [scope]: _, ...rest } = map;
|
|
15070
|
-
return { [kind]: rest };
|
|
15071
|
-
}
|
|
15072
|
-
if (scope === "root") {
|
|
15073
|
-
const next = {};
|
|
15074
|
-
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15075
|
-
return { [kind]: next };
|
|
15076
|
-
}
|
|
15077
|
-
return { [kind]: {} };
|
|
15078
|
-
});
|
|
15067
|
+
return { color: background, background: true };
|
|
15068
|
+
}
|
|
15069
|
+
return null;
|
|
15079
15070
|
}
|
|
15080
15071
|
|
|
15081
|
-
function
|
|
15082
|
-
const
|
|
15083
|
-
|
|
15084
|
-
|
|
15072
|
+
function parseRendererConfig(rendererProp) {
|
|
15073
|
+
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
15074
|
+
if (isRendererConfig) {
|
|
15075
|
+
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
15076
|
+
return {
|
|
15077
|
+
primaryCanvas: pc,
|
|
15078
|
+
scheduler: sc,
|
|
15079
|
+
renderer: Object.keys(rest).length > 0 ? rest : rendererProp
|
|
15080
|
+
};
|
|
15081
|
+
}
|
|
15082
|
+
return { primaryCanvas: void 0, scheduler: void 0, renderer: rendererProp };
|
|
15085
15083
|
}
|
|
15086
15084
|
|
|
15087
15085
|
function CanvasImpl({
|
|
@@ -15121,9 +15119,9 @@ function CanvasImpl({
|
|
|
15121
15119
|
React__namespace.useMemo(() => extend(THREE), []);
|
|
15122
15120
|
const Bridge = useBridge();
|
|
15123
15121
|
const backgroundProps = React__namespace.useMemo(() => parseBackground(background), [background]);
|
|
15124
|
-
const
|
|
15122
|
+
const [hasInitialSize, setHasInitialSize] = React__namespace.useState(false);
|
|
15125
15123
|
const measureConfig = React__namespace.useMemo(() => {
|
|
15126
|
-
if (!
|
|
15124
|
+
if (!hasInitialSize) {
|
|
15127
15125
|
return {
|
|
15128
15126
|
...resize,
|
|
15129
15127
|
scroll: resize?.scroll ?? true,
|
|
@@ -15135,7 +15133,7 @@ function CanvasImpl({
|
|
|
15135
15133
|
debounce: { scroll: 50, resize: 0 },
|
|
15136
15134
|
...resize
|
|
15137
15135
|
};
|
|
15138
|
-
}, [
|
|
15136
|
+
}, [hasInitialSize, resize]);
|
|
15139
15137
|
const [containerRef, containerRect] = useMeasure__default(measureConfig);
|
|
15140
15138
|
const effectiveSize = React__namespace.useMemo(() => {
|
|
15141
15139
|
let w = width ?? containerRect.width;
|
|
@@ -15151,9 +15149,7 @@ function CanvasImpl({
|
|
|
15151
15149
|
left: containerRect.left
|
|
15152
15150
|
};
|
|
15153
15151
|
}, [width, height, containerRect, forceEven]);
|
|
15154
|
-
if (!
|
|
15155
|
-
hasInitialSizeRef.current = true;
|
|
15156
|
-
}
|
|
15152
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15157
15153
|
const canvasRef = React__namespace.useRef(null);
|
|
15158
15154
|
const divRef = React__namespace.useRef(null);
|
|
15159
15155
|
React__namespace.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15267,6 +15263,7 @@ function CanvasImpl({
|
|
|
15267
15263
|
const canvas = canvasRef.current;
|
|
15268
15264
|
if (canvas) {
|
|
15269
15265
|
return () => {
|
|
15266
|
+
if (canvas.isConnected) return;
|
|
15270
15267
|
unmountComponentAtNode(canvas);
|
|
15271
15268
|
root.current = null;
|
|
15272
15269
|
};
|
|
@@ -15279,7 +15276,7 @@ function CanvasImpl({
|
|
|
15279
15276
|
const handleHMR = () => {
|
|
15280
15277
|
queueMicrotask(() => {
|
|
15281
15278
|
const rootEntry = _roots.get(canvas);
|
|
15282
|
-
if (rootEntry?.store)
|
|
15279
|
+
if (rootEntry?.store) notifyRootExtensionsHmr(rootEntry.store);
|
|
15283
15280
|
});
|
|
15284
15281
|
};
|
|
15285
15282
|
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
@@ -15325,20 +15322,159 @@ function CanvasImpl({
|
|
|
15325
15322
|
}
|
|
15326
15323
|
);
|
|
15327
15324
|
}
|
|
15328
|
-
function Canvas(props) {
|
|
15325
|
+
function Canvas$1(props) {
|
|
15329
15326
|
return /* @__PURE__ */ jsxRuntime.jsx(itsFine.FiberProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(CanvasImpl, { ...props }) });
|
|
15330
15327
|
}
|
|
15331
15328
|
|
|
15329
|
+
const RESOURCE_KINDS = ["nodes", "uniforms", "buffers", "gpuStorage"];
|
|
15330
|
+
const ROOT_SCOPE = "";
|
|
15331
|
+
const registries = /* @__PURE__ */ new WeakMap();
|
|
15332
|
+
function getKindRegistry(store, kind) {
|
|
15333
|
+
let registry = registries.get(store);
|
|
15334
|
+
if (!registry) {
|
|
15335
|
+
registry = {
|
|
15336
|
+
nodes: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
15337
|
+
uniforms: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
15338
|
+
buffers: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() },
|
|
15339
|
+
gpuStorage: { valid: /* @__PURE__ */ new Set(), staged: /* @__PURE__ */ new Map() }
|
|
15340
|
+
};
|
|
15341
|
+
registries.set(store, registry);
|
|
15342
|
+
}
|
|
15343
|
+
return registry[kind];
|
|
15344
|
+
}
|
|
15345
|
+
function resolvePrimary$1(store) {
|
|
15346
|
+
return store.getState().primaryStore ?? store;
|
|
15347
|
+
}
|
|
15348
|
+
function isScopeValid(store, kind, scopeKey) {
|
|
15349
|
+
return getKindRegistry(store, kind).valid.has(scopeKey);
|
|
15350
|
+
}
|
|
15351
|
+
function peekStaged(store, kind, scopeKey) {
|
|
15352
|
+
return getKindRegistry(store, kind).staged.get(scopeKey);
|
|
15353
|
+
}
|
|
15354
|
+
function stageEntries(store, kind, scopeKey, entries) {
|
|
15355
|
+
const { staged } = getKindRegistry(store, kind);
|
|
15356
|
+
const current = staged.get(scopeKey);
|
|
15357
|
+
if (current) Object.assign(current, entries);
|
|
15358
|
+
else staged.set(scopeKey, { ...entries });
|
|
15359
|
+
}
|
|
15360
|
+
function readCommittedScope(map, scopeKey, isLeaf) {
|
|
15361
|
+
if (scopeKey === ROOT_SCOPE) {
|
|
15362
|
+
const leaves = {};
|
|
15363
|
+
for (const [key, value] of Object.entries(map)) if (isLeaf(value)) leaves[key] = value;
|
|
15364
|
+
return leaves;
|
|
15365
|
+
}
|
|
15366
|
+
const scopeData = map[scopeKey];
|
|
15367
|
+
if (scopeData && typeof scopeData === "object" && !isLeaf(scopeData)) return scopeData;
|
|
15368
|
+
return {};
|
|
15369
|
+
}
|
|
15370
|
+
function withStagedOverlay(store, kind, committed) {
|
|
15371
|
+
const { staged } = getKindRegistry(store, kind);
|
|
15372
|
+
if (staged.size === 0) return committed;
|
|
15373
|
+
const view = { ...committed };
|
|
15374
|
+
for (const [scopeKey, entries] of staged) {
|
|
15375
|
+
if (scopeKey === ROOT_SCOPE) Object.assign(view, entries);
|
|
15376
|
+
else view[scopeKey] = { ...view[scopeKey], ...entries };
|
|
15377
|
+
}
|
|
15378
|
+
return view;
|
|
15379
|
+
}
|
|
15380
|
+
function flushStagedScope(store, kind, scopeKey, isLeaf) {
|
|
15381
|
+
const registry = getKindRegistry(store, kind);
|
|
15382
|
+
const staged = registry.staged.get(scopeKey);
|
|
15383
|
+
if (!staged) return;
|
|
15384
|
+
registry.staged.delete(scopeKey);
|
|
15385
|
+
const replace = !registry.valid.has(scopeKey);
|
|
15386
|
+
store.setState((state) => {
|
|
15387
|
+
const map = state[kind];
|
|
15388
|
+
if (scopeKey === ROOT_SCOPE) {
|
|
15389
|
+
if (!replace) return { [kind]: { ...map, ...staged } };
|
|
15390
|
+
const next = {};
|
|
15391
|
+
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15392
|
+
return { [kind]: { ...next, ...staged } };
|
|
15393
|
+
}
|
|
15394
|
+
const current = replace ? {} : map[scopeKey] ?? {};
|
|
15395
|
+
return { [kind]: { ...map, [scopeKey]: { ...current, ...staged } } };
|
|
15396
|
+
});
|
|
15397
|
+
registry.valid.add(scopeKey);
|
|
15398
|
+
}
|
|
15399
|
+
function invalidateResource(store, kind, scopeKey) {
|
|
15400
|
+
const registry = getKindRegistry(store, kind);
|
|
15401
|
+
if (scopeKey === void 0) {
|
|
15402
|
+
registry.valid.clear();
|
|
15403
|
+
registry.staged.clear();
|
|
15404
|
+
} else {
|
|
15405
|
+
registry.valid.delete(scopeKey);
|
|
15406
|
+
registry.staged.delete(scopeKey);
|
|
15407
|
+
}
|
|
15408
|
+
}
|
|
15409
|
+
function rebuildResource(store, kind, userScope) {
|
|
15410
|
+
const primary = resolvePrimary$1(store);
|
|
15411
|
+
invalidateResource(primary, kind, userScope === "root" ? ROOT_SCOPE : userScope);
|
|
15412
|
+
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
15413
|
+
}
|
|
15414
|
+
function invalidateAllResources(store) {
|
|
15415
|
+
for (const kind of RESOURCE_KINDS) invalidateResource(store, kind);
|
|
15416
|
+
}
|
|
15417
|
+
function removeResourceEntries(store, kind, names, scope, isLeaf) {
|
|
15418
|
+
const staged = peekStaged(store, kind, scope ?? ROOT_SCOPE);
|
|
15419
|
+
if (staged) for (const name of names) delete staged[name];
|
|
15420
|
+
store.setState((state) => {
|
|
15421
|
+
const map = state[kind];
|
|
15422
|
+
if (scope) {
|
|
15423
|
+
const currentScope = { ...map[scope] };
|
|
15424
|
+
for (const name of names) delete currentScope[name];
|
|
15425
|
+
return { [kind]: { ...map, [scope]: currentScope } };
|
|
15426
|
+
}
|
|
15427
|
+
const next = { ...map };
|
|
15428
|
+
for (const name of names) if (isLeaf(next[name])) delete next[name];
|
|
15429
|
+
return { [kind]: next };
|
|
15430
|
+
});
|
|
15431
|
+
}
|
|
15432
|
+
function clearResourceEntries(store, kind, scope, isLeaf) {
|
|
15433
|
+
const registry = getKindRegistry(store, kind);
|
|
15434
|
+
if (scope && scope !== "root") registry.staged.delete(scope);
|
|
15435
|
+
else if (scope === "root") registry.staged.delete(ROOT_SCOPE);
|
|
15436
|
+
else registry.staged.clear();
|
|
15437
|
+
store.setState((state) => {
|
|
15438
|
+
const map = state[kind];
|
|
15439
|
+
if (scope && scope !== "root") {
|
|
15440
|
+
const { [scope]: _, ...rest } = map;
|
|
15441
|
+
return { [kind]: rest };
|
|
15442
|
+
}
|
|
15443
|
+
if (scope === "root") {
|
|
15444
|
+
const next = {};
|
|
15445
|
+
for (const [key, value] of Object.entries(map)) if (!isLeaf(value)) next[key] = value;
|
|
15446
|
+
return { [kind]: next };
|
|
15447
|
+
}
|
|
15448
|
+
return { [kind]: {} };
|
|
15449
|
+
});
|
|
15450
|
+
}
|
|
15451
|
+
|
|
15452
|
+
const isObjectLike = (value) => value !== null && (typeof value === "object" || typeof value === "function");
|
|
15453
|
+
const hasValidLegacyNodeMarkers = (value) => {
|
|
15454
|
+
const hasUuid = "uuid" in value;
|
|
15455
|
+
const hasNodeType = "nodeType" in value;
|
|
15456
|
+
const uuid = Reflect.get(value, "uuid");
|
|
15457
|
+
const nodeType = Reflect.get(value, "nodeType");
|
|
15458
|
+
return (hasUuid || hasNodeType) && (!hasUuid || uuid === void 0 || typeof uuid === "string") && (!hasNodeType || nodeType === void 0 || nodeType === null || typeof nodeType === "string");
|
|
15459
|
+
};
|
|
15460
|
+
const isUniformNode = (value) => isObjectLike(value) && "isUniformNode" in value && value.isUniformNode === true;
|
|
15461
|
+
const isTSLNode = (value) => isObjectLike(value) && (Reflect.get(value, "isNode") === true || Reflect.get(value, "shaderNode") !== void 0 && typeof Reflect.get(value, "id") === "number" || hasValidLegacyNodeMarkers(value));
|
|
15462
|
+
const isBufferLike = (value) => ArrayBuffer.isView(value) && !(value instanceof DataView) || isObjectLike(value) && ("isBufferAttribute" in value || "isInterleavedBufferAttribute" in value || isTSLNode(value));
|
|
15463
|
+
const isStorageLike = (value) => isObjectLike(value) && ("isTexture" in value || "isData3DTexture" in value || isTSLNode(value));
|
|
15464
|
+
|
|
15332
15465
|
var __defProp = Object.defineProperty;
|
|
15333
15466
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
15334
15467
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
15335
|
-
var _a;
|
|
15468
|
+
var _a, _b;
|
|
15336
15469
|
const INTERNAL_DATA = Symbol("ScopedStore.data");
|
|
15337
|
-
|
|
15470
|
+
const INTERNAL_IS_LEAF = Symbol("ScopedStore.isLeaf");
|
|
15471
|
+
_b = INTERNAL_DATA, _a = INTERNAL_IS_LEAF;
|
|
15338
15472
|
const _ScopedStore = class _ScopedStore {
|
|
15339
|
-
constructor(data) {
|
|
15473
|
+
constructor(data, isLeaf) {
|
|
15474
|
+
__publicField(this, _b);
|
|
15340
15475
|
__publicField(this, _a);
|
|
15341
15476
|
this[INTERNAL_DATA] = data;
|
|
15477
|
+
this[INTERNAL_IS_LEAF] = isLeaf;
|
|
15342
15478
|
return new Proxy(this, {
|
|
15343
15479
|
get(target, prop, receiver) {
|
|
15344
15480
|
if (typeof prop === "string") {
|
|
@@ -15372,10 +15508,10 @@ const _ScopedStore = class _ScopedStore {
|
|
|
15372
15508
|
* If the key doesn't exist or isn't a scope object, returns an empty ScopedStore.
|
|
15373
15509
|
*/
|
|
15374
15510
|
scope(key) {
|
|
15375
|
-
const
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
);
|
|
15511
|
+
const value = this[INTERNAL_DATA][key];
|
|
15512
|
+
const isLeaf = this[INTERNAL_IS_LEAF];
|
|
15513
|
+
const scope = value && typeof value === "object" && !isLeaf(value) ? value : {};
|
|
15514
|
+
return new _ScopedStore(scope, isLeaf);
|
|
15379
15515
|
}
|
|
15380
15516
|
/**
|
|
15381
15517
|
* Check if a key exists in the store.
|
|
@@ -15391,8 +15527,8 @@ const _ScopedStore = class _ScopedStore {
|
|
|
15391
15527
|
}
|
|
15392
15528
|
};
|
|
15393
15529
|
let ScopedStore = _ScopedStore;
|
|
15394
|
-
function createScopedStore(data) {
|
|
15395
|
-
return new ScopedStore(data);
|
|
15530
|
+
function createScopedStore(data, isLeaf) {
|
|
15531
|
+
return new ScopedStore(data, isLeaf);
|
|
15396
15532
|
}
|
|
15397
15533
|
function createLazyCreatorState(state, store) {
|
|
15398
15534
|
let _uniforms = null;
|
|
@@ -15403,22 +15539,22 @@ function createLazyCreatorState(state, store) {
|
|
|
15403
15539
|
return Object.create(state, {
|
|
15404
15540
|
uniforms: {
|
|
15405
15541
|
get() {
|
|
15406
|
-
return _uniforms ?? (_uniforms = createScopedStore(view("uniforms")));
|
|
15542
|
+
return _uniforms ?? (_uniforms = createScopedStore(view("uniforms"), isUniformNode));
|
|
15407
15543
|
}
|
|
15408
15544
|
},
|
|
15409
15545
|
nodes: {
|
|
15410
15546
|
get() {
|
|
15411
|
-
return _nodes ?? (_nodes = createScopedStore(view("nodes")));
|
|
15547
|
+
return _nodes ?? (_nodes = createScopedStore(view("nodes"), isTSLNode));
|
|
15412
15548
|
}
|
|
15413
15549
|
},
|
|
15414
15550
|
buffers: {
|
|
15415
15551
|
get() {
|
|
15416
|
-
return _buffers ?? (_buffers = createScopedStore(view("buffers")));
|
|
15552
|
+
return _buffers ?? (_buffers = createScopedStore(view("buffers"), isBufferLike));
|
|
15417
15553
|
}
|
|
15418
15554
|
},
|
|
15419
15555
|
gpuStorage: {
|
|
15420
15556
|
get() {
|
|
15421
|
-
return _gpuStorage ?? (_gpuStorage = createScopedStore(view("gpuStorage")));
|
|
15557
|
+
return _gpuStorage ?? (_gpuStorage = createScopedStore(view("gpuStorage"), isStorageLike));
|
|
15422
15558
|
}
|
|
15423
15559
|
}
|
|
15424
15560
|
});
|
|
@@ -15438,44 +15574,10 @@ function usePrimaryThree(selector = (state) => state, equalityFn) {
|
|
|
15438
15574
|
return primary(selector, equalityFn);
|
|
15439
15575
|
}
|
|
15440
15576
|
|
|
15441
|
-
function
|
|
15442
|
-
|
|
15443
|
-
|
|
15444
|
-
|
|
15445
|
-
return { textures: newMap };
|
|
15446
|
-
});
|
|
15447
|
-
}
|
|
15448
|
-
function addTextures(set, items) {
|
|
15449
|
-
set((state) => {
|
|
15450
|
-
const newMap = new Map(state.textures);
|
|
15451
|
-
const entries = items instanceof Map ? items.entries() : Object.entries(items);
|
|
15452
|
-
for (const [key, value] of entries) {
|
|
15453
|
-
newMap.set(key, value);
|
|
15454
|
-
}
|
|
15455
|
-
return { textures: newMap };
|
|
15456
|
-
});
|
|
15457
|
-
}
|
|
15458
|
-
function removeTexture(set, key) {
|
|
15459
|
-
set((state) => {
|
|
15460
|
-
const newMap = new Map(state.textures);
|
|
15461
|
-
newMap.delete(key);
|
|
15462
|
-
return { textures: newMap };
|
|
15463
|
-
});
|
|
15464
|
-
}
|
|
15465
|
-
function removeTextures(set, keys) {
|
|
15466
|
-
set((state) => {
|
|
15467
|
-
const newMap = new Map(state.textures);
|
|
15468
|
-
for (const key of keys) newMap.delete(key);
|
|
15469
|
-
return { textures: newMap };
|
|
15470
|
-
});
|
|
15471
|
-
}
|
|
15472
|
-
function createTextureOperations(set) {
|
|
15473
|
-
return {
|
|
15474
|
-
add: (key, value) => addTexture(set, key, value),
|
|
15475
|
-
addMultiple: (items) => addTextures(set, items),
|
|
15476
|
-
remove: (key) => removeTexture(set, key),
|
|
15477
|
-
removeMultiple: (keys) => removeTextures(set, keys)
|
|
15478
|
-
};
|
|
15577
|
+
function scopedNodeName(scope, name) {
|
|
15578
|
+
const raw = scope ? `${scope}_${name}` : name;
|
|
15579
|
+
const safe = raw.replace(/[^A-Za-z0-9_]/g, "_");
|
|
15580
|
+
return /^[A-Za-z_]/.test(safe) ? safe : `_${safe}`;
|
|
15479
15581
|
}
|
|
15480
15582
|
function extractTSLValue(value) {
|
|
15481
15583
|
if (value === null || value === void 0) return value;
|
|
@@ -15514,7 +15616,7 @@ function vectorize(inObject) {
|
|
|
15514
15616
|
return extractTSLValue(inObject);
|
|
15515
15617
|
}
|
|
15516
15618
|
if (obj.isVector2 || obj.isVector3 || obj.isVector4) return inObject;
|
|
15517
|
-
if (obj.isMatrix3 || obj.isMatrix4) return inObject;
|
|
15619
|
+
if (obj.isMatrix2 || obj.isMatrix3 || obj.isMatrix4) return inObject;
|
|
15518
15620
|
if (obj.isColor || obj.isEuler || obj.isQuaternion || obj.isSpherical) return inObject;
|
|
15519
15621
|
if ("r" in obj && "g" in obj && "b" in obj && typeof obj.r === "number" && typeof obj.g === "number" && typeof obj.b === "number") {
|
|
15520
15622
|
const scale = obj.r > 1 || obj.g > 1 || obj.b > 1 ? 1 / 255 : 1;
|
|
@@ -15541,6 +15643,47 @@ function useCompareMemoize(value, deep) {
|
|
|
15541
15643
|
return ref.current;
|
|
15542
15644
|
}
|
|
15543
15645
|
|
|
15646
|
+
function clearHmrCaches(store) {
|
|
15647
|
+
const primary = store.getState().primaryStore ?? store;
|
|
15648
|
+
invalidateAllResources(primary);
|
|
15649
|
+
primary.setState((state) => ({ _hmrVersion: state._hmrVersion + 1 }));
|
|
15650
|
+
}
|
|
15651
|
+
|
|
15652
|
+
const SHARED_KEYS = ["uniforms", "nodes", "buffers", "gpuStorage", "_hmrVersion"];
|
|
15653
|
+
const following = /* @__PURE__ */ new WeakMap();
|
|
15654
|
+
function followPrimary(store) {
|
|
15655
|
+
const primary = store.getState().primaryStore;
|
|
15656
|
+
if (!primary || primary === store) return;
|
|
15657
|
+
const sync = () => {
|
|
15658
|
+
const source = primary.getState();
|
|
15659
|
+
const target = store.getState();
|
|
15660
|
+
let patch = null;
|
|
15661
|
+
for (const key of SHARED_KEYS) {
|
|
15662
|
+
if (target[key] !== source[key]) (patch ?? (patch = {}))[key] = source[key];
|
|
15663
|
+
}
|
|
15664
|
+
if (patch) store.setState(patch);
|
|
15665
|
+
};
|
|
15666
|
+
sync();
|
|
15667
|
+
following.set(store, primary.subscribe(sync));
|
|
15668
|
+
}
|
|
15669
|
+
function stopFollowing(store) {
|
|
15670
|
+
following.get(store)?.();
|
|
15671
|
+
following.delete(store);
|
|
15672
|
+
}
|
|
15673
|
+
let registered = false;
|
|
15674
|
+
function ensureTSLExtension() {
|
|
15675
|
+
if (registered) return;
|
|
15676
|
+
registered = true;
|
|
15677
|
+
registerRootExtension({
|
|
15678
|
+
name: "@react-three/tsl",
|
|
15679
|
+
setup: followPrimary,
|
|
15680
|
+
dispose: stopFollowing,
|
|
15681
|
+
// Resolves primaryStore itself, so every canvas sharing a renderer refreshes the same resources.
|
|
15682
|
+
hmr: clearHmrCaches
|
|
15683
|
+
});
|
|
15684
|
+
}
|
|
15685
|
+
|
|
15686
|
+
ensureTSLExtension();
|
|
15544
15687
|
function useScopedResource(options) {
|
|
15545
15688
|
const { store, kind, scope, isLeaf, create, prepare, reconcile, input } = options;
|
|
15546
15689
|
const scopeKey = scope ?? ROOT_SCOPE;
|
|
@@ -15572,22 +15715,21 @@ function useScopedResource(options) {
|
|
|
15572
15715
|
return entries;
|
|
15573
15716
|
}
|
|
15574
15717
|
|
|
15575
|
-
const isUniformNode$1 = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
|
|
15576
15718
|
function useUniforms(creatorOrScope, scope) {
|
|
15577
15719
|
const store = usePrimaryStore();
|
|
15578
15720
|
const removeUniforms2 = React.useCallback(
|
|
15579
|
-
(names, targetScope) => removeResourceEntries(store, "uniforms", Array.isArray(names) ? names : [names], targetScope, isUniformNode
|
|
15721
|
+
(names, targetScope) => removeResourceEntries(store, "uniforms", Array.isArray(names) ? names : [names], targetScope, isUniformNode),
|
|
15580
15722
|
[store]
|
|
15581
15723
|
);
|
|
15582
15724
|
const clearUniforms = React.useCallback(
|
|
15583
|
-
(targetScope) => clearResourceEntries(store, "uniforms", targetScope, isUniformNode
|
|
15725
|
+
(targetScope) => clearResourceEntries(store, "uniforms", targetScope, isUniformNode),
|
|
15584
15726
|
[store]
|
|
15585
15727
|
);
|
|
15586
15728
|
const rebuildUniforms = React.useCallback(
|
|
15587
15729
|
(targetScope) => rebuildResource(store, "uniforms", targetScope),
|
|
15588
15730
|
[store]
|
|
15589
15731
|
);
|
|
15590
|
-
const
|
|
15732
|
+
const processedInput = React.useMemo(() => {
|
|
15591
15733
|
let raw = creatorOrScope;
|
|
15592
15734
|
if (is.fun(creatorOrScope)) {
|
|
15593
15735
|
const wrappedState = createLazyCreatorState(store.getState(), store);
|
|
@@ -15598,23 +15740,24 @@ function useUniforms(creatorOrScope, scope) {
|
|
|
15598
15740
|
for (const [key, value] of Object.entries(raw)) {
|
|
15599
15741
|
normalized[key] = vectorize(value);
|
|
15600
15742
|
}
|
|
15601
|
-
return normalized;
|
|
15743
|
+
return { candidates: raw, normalized };
|
|
15602
15744
|
}
|
|
15603
|
-
return raw;
|
|
15745
|
+
return { candidates: raw, normalized: raw };
|
|
15604
15746
|
}, [creatorOrScope, store]);
|
|
15605
|
-
const memoizedInput = useCompareMemoize(
|
|
15747
|
+
const memoizedInput = useCompareMemoize(processedInput.normalized);
|
|
15606
15748
|
const isReader = memoizedInput === void 0 || typeof memoizedInput === "string";
|
|
15607
15749
|
const storeUniforms = usePrimaryThree((s) => s.uniforms);
|
|
15608
15750
|
const created = useScopedResource({
|
|
15609
15751
|
store,
|
|
15610
15752
|
kind: "uniforms",
|
|
15611
15753
|
scope: isReader ? void 0 : scope,
|
|
15612
|
-
isLeaf: isUniformNode
|
|
15754
|
+
isLeaf: isUniformNode,
|
|
15613
15755
|
input: memoizedInput,
|
|
15614
15756
|
create: () => {
|
|
15615
15757
|
if (isReader) return {};
|
|
15616
|
-
if (typeof
|
|
15617
|
-
|
|
15758
|
+
if (typeof processedInput.candidates !== "object" || processedInput.candidates === null)
|
|
15759
|
+
throw new Error("Invalid uniform input");
|
|
15760
|
+
return processedInput.candidates;
|
|
15618
15761
|
},
|
|
15619
15762
|
prepare: (name, candidate) => createUniform(name, candidate, scope),
|
|
15620
15763
|
reconcile: (existing, candidate) => {
|
|
@@ -15636,7 +15779,7 @@ function useUniforms(creatorOrScope, scope) {
|
|
|
15636
15779
|
uniforms = storeUniforms;
|
|
15637
15780
|
} else if (typeof memoizedInput === "string") {
|
|
15638
15781
|
const scopeData = storeUniforms[memoizedInput];
|
|
15639
|
-
uniforms = scopeData && !isUniformNode
|
|
15782
|
+
uniforms = scopeData && !isUniformNode(scopeData) ? scopeData : {};
|
|
15640
15783
|
}
|
|
15641
15784
|
return { ...uniforms, removeUniforms: removeUniforms2, clearUniforms, rebuildUniforms };
|
|
15642
15785
|
}
|
|
@@ -15651,7 +15794,7 @@ function removeUniforms(set, names, scope) {
|
|
|
15651
15794
|
return { uniforms: { ...state.uniforms, [scope]: currentScope } };
|
|
15652
15795
|
}
|
|
15653
15796
|
const uniforms = { ...state.uniforms };
|
|
15654
|
-
for (const name of names) if (isUniformNode
|
|
15797
|
+
for (const name of names) if (isUniformNode(uniforms[name])) delete uniforms[name];
|
|
15655
15798
|
return { uniforms };
|
|
15656
15799
|
});
|
|
15657
15800
|
}
|
|
@@ -15665,7 +15808,7 @@ function clearRootUniforms(set) {
|
|
|
15665
15808
|
set((state) => {
|
|
15666
15809
|
const uniforms = {};
|
|
15667
15810
|
for (const [key, value] of Object.entries(state.uniforms)) {
|
|
15668
|
-
if (!isUniformNode
|
|
15811
|
+
if (!isUniformNode(value)) uniforms[key] = value;
|
|
15669
15812
|
}
|
|
15670
15813
|
return { uniforms };
|
|
15671
15814
|
});
|
|
@@ -15675,8 +15818,7 @@ function createUniform(inName, node, scope) {
|
|
|
15675
15818
|
const inValue = vectorize(node);
|
|
15676
15819
|
const newUniform = tsl.uniform(inValue);
|
|
15677
15820
|
if (typeof newUniform.setName === "function") {
|
|
15678
|
-
|
|
15679
|
-
newUniform.setName(name);
|
|
15821
|
+
newUniform.setName(scopedNodeName(scope, inName));
|
|
15680
15822
|
}
|
|
15681
15823
|
return newUniform;
|
|
15682
15824
|
}
|
|
@@ -15702,14 +15844,12 @@ function hasEqualsMethod(value) {
|
|
|
15702
15844
|
function isSameThreeType(a, b) {
|
|
15703
15845
|
const obj_a = a;
|
|
15704
15846
|
const obj_b = b;
|
|
15705
|
-
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;
|
|
15847
|
+
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;
|
|
15706
15848
|
}
|
|
15707
15849
|
|
|
15708
15850
|
const uniformOf = tsl.uniform;
|
|
15709
|
-
const isUniformNode = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
|
|
15710
|
-
const isTSLNode$1 = (value) => value !== null && typeof value === "object" && "uuid" in value && "nodeType" in value;
|
|
15711
15851
|
function useUniform(name, value) {
|
|
15712
|
-
const store =
|
|
15852
|
+
const store = usePrimaryStore();
|
|
15713
15853
|
const registered = useScopedResource({
|
|
15714
15854
|
store,
|
|
15715
15855
|
kind: "uniforms",
|
|
@@ -15719,7 +15859,7 @@ function useUniform(name, value) {
|
|
|
15719
15859
|
create: () => value === void 0 ? {} : { [name]: value },
|
|
15720
15860
|
prepare: createNamedUniform,
|
|
15721
15861
|
reconcile: (existing2) => {
|
|
15722
|
-
if (value !== void 0 && !isTSLNode
|
|
15862
|
+
if (value !== void 0 && !isTSLNode(value) && !isUniformNode(value)) {
|
|
15723
15863
|
existing2.value = typeof value === "string" ? new webgpu.Color(value) : value;
|
|
15724
15864
|
}
|
|
15725
15865
|
}
|
|
@@ -15735,7 +15875,7 @@ function createNamedUniform(name, value) {
|
|
|
15735
15875
|
let node;
|
|
15736
15876
|
if (isUniformNode(value)) {
|
|
15737
15877
|
node = value;
|
|
15738
|
-
} else if (isTSLNode
|
|
15878
|
+
} else if (isTSLNode(value)) {
|
|
15739
15879
|
node = uniformOf(value);
|
|
15740
15880
|
} else if (typeof value === "string") {
|
|
15741
15881
|
node = tsl.uniform(new webgpu.Color(value));
|
|
@@ -15748,7 +15888,6 @@ function createNamedUniform(name, value) {
|
|
|
15748
15888
|
return node;
|
|
15749
15889
|
}
|
|
15750
15890
|
|
|
15751
|
-
const isTSLNode = (value) => value !== null && typeof value === "object" && ("uuid" in value || "nodeType" in value);
|
|
15752
15891
|
function useNodes(creatorOrScope, scope) {
|
|
15753
15892
|
const store = usePrimaryStore();
|
|
15754
15893
|
const removeNodes2 = React.useCallback(
|
|
@@ -15775,7 +15914,8 @@ function useNodes(creatorOrScope, scope) {
|
|
|
15775
15914
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15776
15915
|
},
|
|
15777
15916
|
prepare: (name, node) => {
|
|
15778
|
-
|
|
15917
|
+
const setName = Reflect.get(node, "setName");
|
|
15918
|
+
if (typeof setName === "function") setName.call(node, scopedNodeName(scope, name));
|
|
15779
15919
|
return node;
|
|
15780
15920
|
}
|
|
15781
15921
|
});
|
|
@@ -15830,13 +15970,6 @@ function useLocalNodes(creator) {
|
|
|
15830
15970
|
}, [store, creator, uniforms, nodes, textures, hmrVersion]);
|
|
15831
15971
|
}
|
|
15832
15972
|
|
|
15833
|
-
const isBufferLike = (value) => {
|
|
15834
|
-
if (value === null || typeof value !== "object") return false;
|
|
15835
|
-
if (ArrayBuffer.isView(value)) return true;
|
|
15836
|
-
if ("isBufferAttribute" in value) return true;
|
|
15837
|
-
if ("uuid" in value || "nodeType" in value) return true;
|
|
15838
|
-
return false;
|
|
15839
|
-
};
|
|
15840
15973
|
const disposeBuffer = (buffer) => {
|
|
15841
15974
|
if (buffer === null || typeof buffer !== "object") return;
|
|
15842
15975
|
if ("dispose" in buffer && typeof buffer.dispose === "function") {
|
|
@@ -15883,9 +16016,8 @@ function useBuffers(creatorOrScope, scope) {
|
|
|
15883
16016
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15884
16017
|
},
|
|
15885
16018
|
prepare: (name, buffer) => {
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
}
|
|
16019
|
+
const setName = Reflect.get(buffer, "setName");
|
|
16020
|
+
if (typeof setName === "function") setName.call(buffer, scopedNodeName(scope, name));
|
|
15889
16021
|
return buffer;
|
|
15890
16022
|
}
|
|
15891
16023
|
});
|
|
@@ -15902,13 +16034,6 @@ function rebuildAllBuffers(store, scope) {
|
|
|
15902
16034
|
rebuildResource(store, "buffers", scope);
|
|
15903
16035
|
}
|
|
15904
16036
|
|
|
15905
|
-
const isStorageLike = (value) => {
|
|
15906
|
-
if (value === null || typeof value !== "object") return false;
|
|
15907
|
-
if ("isTexture" in value) return true;
|
|
15908
|
-
if ("isData3DTexture" in value) return true;
|
|
15909
|
-
if ("uuid" in value || "nodeType" in value) return true;
|
|
15910
|
-
return false;
|
|
15911
|
-
};
|
|
15912
16037
|
const disposeStorage = (storage) => {
|
|
15913
16038
|
if (storage === null || typeof storage !== "object") return;
|
|
15914
16039
|
if ("dispose" in storage && typeof storage.dispose === "function") {
|
|
@@ -15955,10 +16080,9 @@ function useGPUStorage(creatorOrScope, scope) {
|
|
|
15955
16080
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15956
16081
|
},
|
|
15957
16082
|
prepare: (name, storage) => {
|
|
15958
|
-
const label = scope
|
|
15959
|
-
|
|
15960
|
-
|
|
15961
|
-
}
|
|
16083
|
+
const label = scopedNodeName(scope, name);
|
|
16084
|
+
const setName = Reflect.get(storage, "setName");
|
|
16085
|
+
if (typeof setName === "function") setName.call(storage, label);
|
|
15962
16086
|
if ("name" in storage && typeof storage.name === "string") {
|
|
15963
16087
|
storage.name = label;
|
|
15964
16088
|
}
|
|
@@ -15984,11 +16108,58 @@ function rebuildAllStorage(store, scope) {
|
|
|
15984
16108
|
rebuildResource(store, "gpuStorage", scope);
|
|
15985
16109
|
}
|
|
15986
16110
|
|
|
16111
|
+
function addTexture(set, key, value) {
|
|
16112
|
+
set((state) => {
|
|
16113
|
+
const newMap = new Map(state.textures);
|
|
16114
|
+
newMap.set(key, value);
|
|
16115
|
+
return { textures: newMap };
|
|
16116
|
+
});
|
|
16117
|
+
}
|
|
16118
|
+
function addTextures(set, items) {
|
|
16119
|
+
set((state) => {
|
|
16120
|
+
const newMap = new Map(state.textures);
|
|
16121
|
+
const entries = items instanceof Map ? items.entries() : Object.entries(items);
|
|
16122
|
+
for (const [key, value] of entries) {
|
|
16123
|
+
newMap.set(key, value);
|
|
16124
|
+
}
|
|
16125
|
+
return { textures: newMap };
|
|
16126
|
+
});
|
|
16127
|
+
}
|
|
16128
|
+
function removeTexture(set, key) {
|
|
16129
|
+
set((state) => {
|
|
16130
|
+
const newMap = new Map(state.textures);
|
|
16131
|
+
newMap.delete(key);
|
|
16132
|
+
return { textures: newMap };
|
|
16133
|
+
});
|
|
16134
|
+
}
|
|
16135
|
+
function removeTextures(set, keys) {
|
|
16136
|
+
set((state) => {
|
|
16137
|
+
const newMap = new Map(state.textures);
|
|
16138
|
+
for (const key of keys) newMap.delete(key);
|
|
16139
|
+
return { textures: newMap };
|
|
16140
|
+
});
|
|
16141
|
+
}
|
|
16142
|
+
function createTextureOperations(set) {
|
|
16143
|
+
return {
|
|
16144
|
+
add: (key, value) => addTexture(set, key, value),
|
|
16145
|
+
addMultiple: (items) => addTextures(set, items),
|
|
16146
|
+
remove: (key) => removeTexture(set, key),
|
|
16147
|
+
removeMultiple: (keys) => removeTextures(set, keys)
|
|
16148
|
+
};
|
|
16149
|
+
}
|
|
16150
|
+
|
|
16151
|
+
function renderThroughPipeline(store) {
|
|
16152
|
+
return () => {
|
|
16153
|
+
const pipeline = store.getState().renderPipeline;
|
|
16154
|
+
if (pipeline?.render) pipeline.render();
|
|
16155
|
+
};
|
|
16156
|
+
}
|
|
15987
16157
|
function useRenderPipeline(mainCB, setupCB) {
|
|
15988
16158
|
const store = useStore();
|
|
15989
16159
|
const { scene, camera, renderer, isLegacy } = useThree$1();
|
|
15990
16160
|
const callbacksRanRef = React.useRef(false);
|
|
15991
16161
|
const scenePassCacheRef = React.useRef(null);
|
|
16162
|
+
const forceScenePassRebuildRef = React.useRef(false);
|
|
15992
16163
|
const mainCBRef = React.useRef(mainCB);
|
|
15993
16164
|
const setupCBRef = React.useRef(setupCB);
|
|
15994
16165
|
mainCBRef.current = mainCB;
|
|
@@ -15996,7 +16167,7 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15996
16167
|
const [rebuildVersion, setRebuildVersion] = React.useState(0);
|
|
15997
16168
|
React.useEffect(() => {
|
|
15998
16169
|
callbacksRanRef.current = false;
|
|
15999
|
-
|
|
16170
|
+
forceScenePassRebuildRef.current = true;
|
|
16000
16171
|
}, []);
|
|
16001
16172
|
const clearPasses = React.useCallback(() => {
|
|
16002
16173
|
store.setState({ passes: {} });
|
|
@@ -16006,12 +16177,15 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16006
16177
|
renderPipeline: null,
|
|
16007
16178
|
passes: {}
|
|
16008
16179
|
});
|
|
16180
|
+
setRenderOverride(store, null);
|
|
16181
|
+
scenePassCacheRef.current?.scenePass.dispose();
|
|
16009
16182
|
callbacksRanRef.current = false;
|
|
16010
16183
|
scenePassCacheRef.current = null;
|
|
16184
|
+
forceScenePassRebuildRef.current = false;
|
|
16011
16185
|
}, [store]);
|
|
16012
16186
|
const rebuild = React.useCallback(() => {
|
|
16013
16187
|
callbacksRanRef.current = false;
|
|
16014
|
-
|
|
16188
|
+
forceScenePassRebuildRef.current = true;
|
|
16015
16189
|
setRebuildVersion((v) => v + 1);
|
|
16016
16190
|
}, []);
|
|
16017
16191
|
React.useLayoutEffect(() => {
|
|
@@ -16019,6 +16193,9 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16019
16193
|
throw new Error("useRenderPipeline is only available with WebGPU renderer. Set renderer prop on Canvas.");
|
|
16020
16194
|
}
|
|
16021
16195
|
if (!renderer || !scene || !camera) return;
|
|
16196
|
+
if (!("isWebGPURenderer" in renderer)) {
|
|
16197
|
+
throw new Error("useRenderPipeline: renderer is not a WebGPURenderer but isLegacy is false.");
|
|
16198
|
+
}
|
|
16022
16199
|
const state = store.getState();
|
|
16023
16200
|
const set = store.setState;
|
|
16024
16201
|
try {
|
|
@@ -16029,21 +16206,34 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16029
16206
|
pipeline = new webgpu.RenderPipeline(renderer);
|
|
16030
16207
|
justCreatedPipeline = true;
|
|
16031
16208
|
}
|
|
16032
|
-
const cacheValid = scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16209
|
+
const cacheValid = !forceScenePassRebuildRef.current && scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16210
|
+
let outgoingScenePass = null;
|
|
16033
16211
|
let scenePass;
|
|
16034
16212
|
if (cacheValid) {
|
|
16035
16213
|
scenePass = scenePassCacheRef.current.scenePass;
|
|
16036
16214
|
} else {
|
|
16215
|
+
outgoingScenePass = scenePassCacheRef.current?.scenePass ?? null;
|
|
16037
16216
|
scenePass = tsl.pass(scene, camera);
|
|
16038
16217
|
scenePassCacheRef.current = { sceneUuid: scene.uuid, cameraUuid: camera.uuid, scenePass };
|
|
16218
|
+
forceScenePassRebuildRef.current = false;
|
|
16039
16219
|
}
|
|
16040
16220
|
currentPasses.scenePass = scenePass;
|
|
16041
|
-
|
|
16221
|
+
let outputNodeChanged = false;
|
|
16222
|
+
if (!pipeline.outputNode || justCreatedPipeline || pipeline.outputNode === outgoingScenePass) {
|
|
16223
|
+
pipeline.outputNode = scenePass;
|
|
16224
|
+
outputNodeChanged = true;
|
|
16225
|
+
}
|
|
16042
16226
|
set({ renderPipeline: pipeline, passes: currentPasses });
|
|
16227
|
+
setRenderOverride(store, renderThroughPipeline(store));
|
|
16043
16228
|
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid;
|
|
16044
16229
|
if (shouldRunCallbacks) {
|
|
16045
16230
|
if (setupCBRef.current) {
|
|
16046
|
-
const freshState = store.getState()
|
|
16231
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16232
|
+
renderPipeline: pipeline,
|
|
16233
|
+
passes: { ...currentPasses, scenePass },
|
|
16234
|
+
renderer,
|
|
16235
|
+
isLegacy: false
|
|
16236
|
+
});
|
|
16047
16237
|
const setupResult = setupCBRef.current(freshState);
|
|
16048
16238
|
if (setupResult && typeof setupResult === "object") {
|
|
16049
16239
|
currentPasses = { ...currentPasses, ...setupResult };
|
|
@@ -16051,35 +16241,38 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16051
16241
|
}
|
|
16052
16242
|
}
|
|
16053
16243
|
if (mainCBRef.current) {
|
|
16054
|
-
const freshState = store.getState()
|
|
16244
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16245
|
+
renderPipeline: pipeline,
|
|
16246
|
+
passes: { ...currentPasses, scenePass },
|
|
16247
|
+
renderer,
|
|
16248
|
+
isLegacy: false
|
|
16249
|
+
});
|
|
16055
16250
|
const mainResult = mainCBRef.current(freshState);
|
|
16056
16251
|
if (mainResult && typeof mainResult === "object") {
|
|
16057
16252
|
currentPasses = { ...currentPasses, ...mainResult };
|
|
16058
16253
|
set({ passes: currentPasses });
|
|
16059
16254
|
}
|
|
16060
16255
|
}
|
|
16256
|
+
outputNodeChanged = true;
|
|
16061
16257
|
callbacksRanRef.current = true;
|
|
16062
16258
|
}
|
|
16259
|
+
if (outputNodeChanged) pipeline.needsUpdate = true;
|
|
16260
|
+
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose();
|
|
16063
16261
|
} catch (error) {
|
|
16064
16262
|
console.warn("[useRenderPipeline] Setup failed; the render pipeline was not configured:", error);
|
|
16065
16263
|
}
|
|
16066
16264
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16067
16265
|
const passes = useThree$1((s) => s.passes);
|
|
16068
16266
|
const renderPipeline = useThree$1((s) => s.renderPipeline);
|
|
16069
|
-
|
|
16070
|
-
|
|
16071
|
-
|
|
16072
|
-
clearPasses,
|
|
16073
|
-
reset,
|
|
16074
|
-
rebuild,
|
|
16075
|
-
// isReady indicates if RenderPipeline is configured and ready for rendering
|
|
16076
|
-
isReady: renderPipeline !== null
|
|
16077
|
-
};
|
|
16267
|
+
const actions = { passes, clearPasses, reset, rebuild };
|
|
16268
|
+
if (renderPipeline) return { ...actions, isReady: true, renderPipeline };
|
|
16269
|
+
return { ...actions, isReady: false, renderPipeline: null };
|
|
16078
16270
|
}
|
|
16079
16271
|
|
|
16080
16272
|
extend(THREE);
|
|
16081
16273
|
const useThree = useThree$1;
|
|
16082
16274
|
const useFrame = useFrame$1;
|
|
16275
|
+
const Canvas = Canvas$1;
|
|
16083
16276
|
|
|
16084
16277
|
exports.Scheduler = scheduler.Scheduler;
|
|
16085
16278
|
exports.getScheduler = scheduler.getScheduler;
|
|
@@ -16157,10 +16350,12 @@ exports.rebuildAllStorage = rebuildAllStorage;
|
|
|
16157
16350
|
exports.rebuildAllUniforms = rebuildAllUniforms;
|
|
16158
16351
|
exports.reconciler = reconciler;
|
|
16159
16352
|
exports.registerPrimary = registerPrimary;
|
|
16353
|
+
exports.registerRootExtension = registerRootExtension;
|
|
16160
16354
|
exports.removeInteractivity = removeInteractivity;
|
|
16161
16355
|
exports.removeNodes = removeNodes;
|
|
16162
16356
|
exports.removeUniforms = removeUniforms;
|
|
16163
16357
|
exports.resolve = resolve;
|
|
16358
|
+
exports.setRenderOverride = setRenderOverride;
|
|
16164
16359
|
exports.swapInteractivity = swapInteractivity;
|
|
16165
16360
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
16166
16361
|
exports.unregisterPrimary = unregisterPrimary;
|