@react-three/fiber 10.0.0-alpha.1 → 10.0.0-canary.2b511a5

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.
@@ -1,11 +1,17 @@
1
1
  import * as webgpu from 'three/webgpu';
2
- import { RenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1, SRGBColorSpace, Raycaster, OrthographicCamera, PerspectiveCamera, Scene, PCFSoftShadowMap, VSMShadowMap, PCFShadowMap, BasicShadowMap, WebGPURenderer, Color, Vector4, PostProcessing } from 'three/webgpu';
2
+ import { RenderTarget, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Scene, WebGLCubeRenderTarget, HalfFloatType, Color, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, SRGBColorSpace, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1, CanvasTarget, Raycaster, OrthographicCamera, PerspectiveCamera, PCFSoftShadowMap, VSMShadowMap, PCFShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGPURenderer, Vector4, PostProcessing } from 'three/webgpu';
3
3
  import { Inspector } from 'three/addons/inspector/Inspector.js';
4
- import { jsx, Fragment } from 'react/jsx-runtime';
4
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
5
5
  import * as React from 'react';
6
- import React__default, { useMemo, useLayoutEffect, useEffect, useContext, useRef, useImperativeHandle, useCallback, useState } from 'react';
6
+ import React__default, { useLayoutEffect, useRef, useMemo, useEffect, useContext, useImperativeHandle, useCallback, useState } from 'react';
7
7
  import useMeasure from 'react-use-measure';
8
8
  import { useFiber, useContextBridge, traverseFiber, FiberProvider } from 'its-fine';
9
+ import { useThree as useThree$1, useLoader as useLoader$1, useFrame as useFrame$1, createPortal as createPortal$1, applyProps as applyProps$1, extend as extend$1 } from '@react-three/fiber';
10
+ import { GroundedSkybox } from 'three/examples/jsm/objects/GroundedSkybox.js';
11
+ import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
12
+ import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js';
13
+ import { UltraHDRLoader } from 'three/examples/jsm/loaders/UltraHDRLoader.js';
14
+ import { GainMapLoader } from '@monogrid/gainmap-js';
9
15
  import Tb, { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
10
16
  import { createWithEqualityFn } from 'zustand/traditional';
11
17
  import { suspend, preload, clear } from 'suspend-react';
@@ -46,9 +52,377 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
46
52
  WebGLRenderer: WebGLRenderer
47
53
  }, [webgpu]);
48
54
 
49
- var __defProp$2 = Object.defineProperty;
50
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
51
- var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
55
+ const primaryRegistry = /* @__PURE__ */ new Map();
56
+ const pendingSubscribers = /* @__PURE__ */ new Map();
57
+ function registerPrimary(id, renderer, store) {
58
+ if (primaryRegistry.has(id)) {
59
+ console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
60
+ }
61
+ const entry = { renderer, store };
62
+ primaryRegistry.set(id, entry);
63
+ const subscribers = pendingSubscribers.get(id);
64
+ if (subscribers) {
65
+ subscribers.forEach((callback) => callback(entry));
66
+ pendingSubscribers.delete(id);
67
+ }
68
+ return () => {
69
+ const currentEntry = primaryRegistry.get(id);
70
+ if (currentEntry?.renderer === renderer) {
71
+ primaryRegistry.delete(id);
72
+ }
73
+ };
74
+ }
75
+ function getPrimary(id) {
76
+ return primaryRegistry.get(id);
77
+ }
78
+ function waitForPrimary(id, timeout = 5e3) {
79
+ const existing = primaryRegistry.get(id);
80
+ if (existing) {
81
+ return Promise.resolve(existing);
82
+ }
83
+ return new Promise((resolve, reject) => {
84
+ const timeoutId = setTimeout(() => {
85
+ const subscribers = pendingSubscribers.get(id);
86
+ if (subscribers) {
87
+ const index = subscribers.indexOf(callback);
88
+ if (index !== -1) subscribers.splice(index, 1);
89
+ if (subscribers.length === 0) pendingSubscribers.delete(id);
90
+ }
91
+ reject(new Error(`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}"> is mounted.`));
92
+ }, timeout);
93
+ const callback = (entry) => {
94
+ clearTimeout(timeoutId);
95
+ resolve(entry);
96
+ };
97
+ if (!pendingSubscribers.has(id)) {
98
+ pendingSubscribers.set(id, []);
99
+ }
100
+ pendingSubscribers.get(id).push(callback);
101
+ });
102
+ }
103
+ function hasPrimary(id) {
104
+ return primaryRegistry.has(id);
105
+ }
106
+ function unregisterPrimary(id) {
107
+ primaryRegistry.delete(id);
108
+ }
109
+ function getPrimaryIds() {
110
+ return Array.from(primaryRegistry.keys());
111
+ }
112
+
113
+ const presetsObj = {
114
+ apartment: "lebombo_1k.hdr",
115
+ city: "potsdamer_platz_1k.hdr",
116
+ dawn: "kiara_1_dawn_1k.hdr",
117
+ forest: "forest_slope_1k.hdr",
118
+ lobby: "st_fagans_interior_1k.hdr",
119
+ night: "dikhololo_night_1k.hdr",
120
+ park: "rooitou_park_1k.hdr",
121
+ studio: "studio_small_03_1k.hdr",
122
+ sunset: "venice_sunset_1k.hdr",
123
+ warehouse: "empty_warehouse_01_1k.hdr"
124
+ };
125
+
126
+ const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
127
+ const isArray = (arr) => Array.isArray(arr);
128
+ const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
129
+ function useEnvironment({
130
+ files = defaultFiles,
131
+ path = "",
132
+ preset = void 0,
133
+ colorSpace = void 0,
134
+ extensions
135
+ } = {}) {
136
+ if (preset) {
137
+ validatePreset(preset);
138
+ files = presetsObj[preset];
139
+ path = CUBEMAP_ROOT;
140
+ }
141
+ const multiFile = isArray(files);
142
+ const { extension, isCubemap } = getExtension(files);
143
+ const loader = getLoader$1(extension);
144
+ if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
145
+ const renderer = useThree$1((state) => state.renderer);
146
+ useLayoutEffect(() => {
147
+ if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
148
+ function clearGainmapTexture() {
149
+ useLoader$1.clear(loader, multiFile ? [files] : files);
150
+ }
151
+ renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
152
+ }, [files, renderer.domElement]);
153
+ const loaderResult = useLoader$1(
154
+ loader,
155
+ multiFile ? [files] : files,
156
+ (loader2) => {
157
+ if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
158
+ loader2.setRenderer?.(renderer);
159
+ }
160
+ loader2.setPath?.(path);
161
+ if (extensions) extensions(loader2);
162
+ }
163
+ );
164
+ let texture = multiFile ? (
165
+ // @ts-ignore
166
+ loaderResult[0]
167
+ ) : loaderResult;
168
+ if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
169
+ texture = texture.renderTarget?.texture;
170
+ }
171
+ texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
172
+ texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
173
+ return texture;
174
+ }
175
+ const preloadDefaultOptions = {
176
+ files: defaultFiles,
177
+ path: "",
178
+ preset: void 0,
179
+ extensions: void 0
180
+ };
181
+ useEnvironment.preload = (preloadOptions) => {
182
+ const options = { ...preloadDefaultOptions, ...preloadOptions };
183
+ let { files, path = "" } = options;
184
+ const { preset, extensions } = options;
185
+ if (preset) {
186
+ validatePreset(preset);
187
+ files = presetsObj[preset];
188
+ path = CUBEMAP_ROOT;
189
+ }
190
+ const { extension } = getExtension(files);
191
+ if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
192
+ throw new Error("useEnvironment: Preloading gainmaps is not supported");
193
+ }
194
+ const loader = getLoader$1(extension);
195
+ if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
196
+ useLoader$1.preload(loader, isArray(files) ? [files] : files, (loader2) => {
197
+ loader2.setPath?.(path);
198
+ if (extensions) extensions(loader2);
199
+ });
200
+ };
201
+ const clearDefaultOptins = {
202
+ files: defaultFiles,
203
+ preset: void 0
204
+ };
205
+ useEnvironment.clear = (clearOptions) => {
206
+ const options = { ...clearDefaultOptins, ...clearOptions };
207
+ let { files } = options;
208
+ const { preset } = options;
209
+ if (preset) {
210
+ validatePreset(preset);
211
+ files = presetsObj[preset];
212
+ }
213
+ const { extension } = getExtension(files);
214
+ const loader = getLoader$1(extension);
215
+ if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
216
+ useLoader$1.clear(loader, isArray(files) ? [files] : files);
217
+ };
218
+ function validatePreset(preset) {
219
+ if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
220
+ }
221
+ function getExtension(files) {
222
+ const isCubemap = isArray(files) && files.length === 6;
223
+ const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
224
+ const firstEntry = isArray(files) ? files[0] : files;
225
+ const extension = isCubemap ? "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
226
+ return { extension, isCubemap, isGainmap };
227
+ }
228
+ function getLoader$1(extension) {
229
+ const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
230
+ return loader;
231
+ }
232
+
233
+ const isRef$1 = (obj) => obj.current && obj.current.isScene;
234
+ const resolveScene = (scene) => isRef$1(scene) ? scene.current : scene;
235
+ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
236
+ sceneProps = {
237
+ backgroundBlurriness: 0,
238
+ backgroundIntensity: 1,
239
+ backgroundRotation: [0, 0, 0],
240
+ environmentIntensity: 1,
241
+ environmentRotation: [0, 0, 0],
242
+ ...sceneProps
243
+ };
244
+ const target = resolveScene(scene || defaultScene);
245
+ const oldbg = target.background;
246
+ const oldenv = target.environment;
247
+ const oldSceneProps = {
248
+ // @ts-ignore
249
+ backgroundBlurriness: target.backgroundBlurriness,
250
+ // @ts-ignore
251
+ backgroundIntensity: target.backgroundIntensity,
252
+ // @ts-ignore
253
+ backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
254
+ // @ts-ignore
255
+ environmentIntensity: target.environmentIntensity,
256
+ // @ts-ignore
257
+ environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
258
+ };
259
+ if (background !== "only") target.environment = texture;
260
+ if (background) target.background = texture;
261
+ applyProps$1(target, sceneProps);
262
+ return () => {
263
+ if (background !== "only") target.environment = oldenv;
264
+ if (background) target.background = oldbg;
265
+ applyProps$1(target, oldSceneProps);
266
+ };
267
+ }
268
+ function EnvironmentMap({ scene, background = false, map, ...config }) {
269
+ const defaultScene = useThree$1((state) => state.scene);
270
+ React.useLayoutEffect(() => {
271
+ if (map) return setEnvProps(background, scene, defaultScene, map, config);
272
+ });
273
+ return null;
274
+ }
275
+ function EnvironmentCube({
276
+ background = false,
277
+ scene,
278
+ blur,
279
+ backgroundBlurriness,
280
+ backgroundIntensity,
281
+ backgroundRotation,
282
+ environmentIntensity,
283
+ environmentRotation,
284
+ ...rest
285
+ }) {
286
+ const texture = useEnvironment(rest);
287
+ const defaultScene = useThree$1((state) => state.scene);
288
+ React.useLayoutEffect(() => {
289
+ return setEnvProps(background, scene, defaultScene, texture, {
290
+ backgroundBlurriness: blur ?? backgroundBlurriness,
291
+ backgroundIntensity,
292
+ backgroundRotation,
293
+ environmentIntensity,
294
+ environmentRotation
295
+ });
296
+ });
297
+ React.useEffect(() => {
298
+ return () => {
299
+ texture.dispose();
300
+ };
301
+ }, [texture]);
302
+ return null;
303
+ }
304
+ function EnvironmentPortal({
305
+ children,
306
+ near = 0.1,
307
+ far = 1e3,
308
+ resolution = 256,
309
+ frames = 1,
310
+ map,
311
+ background = false,
312
+ blur,
313
+ backgroundBlurriness,
314
+ backgroundIntensity,
315
+ backgroundRotation,
316
+ environmentIntensity,
317
+ environmentRotation,
318
+ scene,
319
+ files,
320
+ path,
321
+ preset = void 0,
322
+ extensions
323
+ }) {
324
+ const gl = useThree$1((state) => state.gl);
325
+ const defaultScene = useThree$1((state) => state.scene);
326
+ const camera = React.useRef(null);
327
+ const [virtualScene] = React.useState(() => new Scene());
328
+ const fbo = React.useMemo(() => {
329
+ const fbo2 = new WebGLCubeRenderTarget(resolution);
330
+ fbo2.texture.type = HalfFloatType;
331
+ return fbo2;
332
+ }, [resolution]);
333
+ React.useEffect(() => {
334
+ return () => {
335
+ fbo.dispose();
336
+ };
337
+ }, [fbo]);
338
+ React.useLayoutEffect(() => {
339
+ if (frames === 1) {
340
+ const autoClear = gl.autoClear;
341
+ gl.autoClear = true;
342
+ camera.current.update(gl, virtualScene);
343
+ gl.autoClear = autoClear;
344
+ }
345
+ return setEnvProps(background, scene, defaultScene, fbo.texture, {
346
+ backgroundBlurriness: blur ?? backgroundBlurriness,
347
+ backgroundIntensity,
348
+ backgroundRotation,
349
+ environmentIntensity,
350
+ environmentRotation
351
+ });
352
+ }, [children, virtualScene, fbo.texture, scene, defaultScene, background, frames, gl]);
353
+ let count = 1;
354
+ useFrame$1(() => {
355
+ if (frames === Infinity || count < frames) {
356
+ const autoClear = gl.autoClear;
357
+ gl.autoClear = true;
358
+ camera.current.update(gl, virtualScene);
359
+ gl.autoClear = autoClear;
360
+ count++;
361
+ }
362
+ });
363
+ return /* @__PURE__ */ jsx(Fragment, { children: createPortal$1(
364
+ /* @__PURE__ */ jsxs(Fragment, { children: [
365
+ children,
366
+ /* @__PURE__ */ jsx("cubeCamera", { ref: camera, args: [near, far, fbo] }),
367
+ files || preset ? /* @__PURE__ */ jsx(EnvironmentCube, { background: true, files, preset, path, extensions }) : map ? /* @__PURE__ */ jsx(EnvironmentMap, { background: true, map, extensions }) : null
368
+ ] }),
369
+ virtualScene
370
+ ) });
371
+ }
372
+ function EnvironmentGround(props) {
373
+ const textureDefault = useEnvironment(props);
374
+ const texture = props.map || textureDefault;
375
+ React.useMemo(() => extend$1({ GroundProjectedEnvImpl: GroundedSkybox }), []);
376
+ React.useEffect(() => {
377
+ return () => {
378
+ textureDefault.dispose();
379
+ };
380
+ }, [textureDefault]);
381
+ const height = props.ground?.height ?? 15;
382
+ const radius = props.ground?.radius ?? 60;
383
+ const scale = props.ground?.scale ?? 1e3;
384
+ const args = React.useMemo(
385
+ () => [texture, height, radius],
386
+ [texture, height, radius]
387
+ );
388
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
389
+ /* @__PURE__ */ jsx(EnvironmentMap, { ...props, map: texture }),
390
+ /* @__PURE__ */ jsx("groundProjectedEnvImpl", { args, scale })
391
+ ] });
392
+ }
393
+ function EnvironmentColor({ color, scene }) {
394
+ const defaultScene = useThree$1((state) => state.scene);
395
+ React.useLayoutEffect(() => {
396
+ if (color === void 0) return;
397
+ const target = resolveScene(scene || defaultScene);
398
+ const oldBg = target.background;
399
+ target.background = new Color(color);
400
+ return () => {
401
+ target.background = oldBg;
402
+ };
403
+ });
404
+ return null;
405
+ }
406
+ function EnvironmentDualSource(props) {
407
+ const { backgroundFiles, ...envProps } = props;
408
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
409
+ /* @__PURE__ */ jsx(EnvironmentCube, { ...envProps, background: false }),
410
+ /* @__PURE__ */ jsx(EnvironmentCube, { ...props, files: backgroundFiles, background: "only" })
411
+ ] });
412
+ }
413
+ function Environment(props) {
414
+ if (props.color && !props.files && !props.preset && !props.map) {
415
+ return /* @__PURE__ */ jsx(EnvironmentColor, { ...props });
416
+ }
417
+ if (props.backgroundFiles && props.backgroundFiles !== props.files) {
418
+ return /* @__PURE__ */ jsx(EnvironmentDualSource, { ...props });
419
+ }
420
+ return props.ground ? /* @__PURE__ */ jsx(EnvironmentGround, { ...props }) : props.map ? /* @__PURE__ */ jsx(EnvironmentMap, { ...props }) : props.children ? /* @__PURE__ */ jsx(EnvironmentPortal, { ...props }) : /* @__PURE__ */ jsx(EnvironmentCube, { ...props });
421
+ }
422
+
423
+ var __defProp$3 = Object.defineProperty;
424
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
425
+ var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
52
426
  const act = React["act"];
53
427
  const useIsomorphicLayoutEffect = /* @__PURE__ */ (() => typeof window !== "undefined" && (window.document?.createElement || window.navigator?.product === "ReactNative"))() ? React.useLayoutEffect : React.useEffect;
54
428
  function useMutableCallback(fn) {
@@ -80,7 +454,7 @@ const ErrorBoundary = /* @__PURE__ */ (() => {
80
454
  return _a = class extends React.Component {
81
455
  constructor() {
82
456
  super(...arguments);
83
- __publicField$2(this, "state", { error: false });
457
+ __publicField$3(this, "state", { error: false });
84
458
  }
85
459
  componentDidCatch(err) {
86
460
  this.props.set(err);
@@ -88,7 +462,7 @@ const ErrorBoundary = /* @__PURE__ */ (() => {
88
462
  render() {
89
463
  return this.state.error ? null : this.props.children;
90
464
  }
91
- }, __publicField$2(_a, "getDerivedStateFromError", () => ({ error: true })), _a;
465
+ }, __publicField$3(_a, "getDerivedStateFromError", () => ({ error: true })), _a;
92
466
  })();
93
467
 
94
468
  const is = {
@@ -225,7 +599,8 @@ function prepare(target, root, type, props) {
225
599
  object,
226
600
  eventCount: 0,
227
601
  handlers: {},
228
- isHidden: false
602
+ isHidden: false,
603
+ deferredRefs: []
229
604
  };
230
605
  if (object) object.__r3f = instance;
231
606
  }
@@ -274,7 +649,7 @@ function createOcclusionObserverNode(store, uniform) {
274
649
  let occlusionSetupPromise = null;
275
650
  function enableOcclusion(store) {
276
651
  const state = store.getState();
277
- const { internal, renderer, rootScene } = state;
652
+ const { internal, renderer } = state;
278
653
  if (internal.occlusionEnabled || occlusionSetupPromise) return;
279
654
  const hasOcclusionSupport = typeof renderer?.isOccluded === "function";
280
655
  if (!hasOcclusionSupport) {
@@ -437,6 +812,22 @@ function hasVisibilityHandlers(handlers) {
437
812
  return !!(handlers.onFramed || handlers.onOccluded || handlers.onVisible);
438
813
  }
439
814
 
815
+ const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
816
+ function fromRef(ref) {
817
+ return { [FROM_REF]: ref };
818
+ }
819
+ function isFromRef(value) {
820
+ return value !== null && typeof value === "object" && FROM_REF in value;
821
+ }
822
+
823
+ const ONCE = Symbol.for("@react-three/fiber.once");
824
+ function once(...args) {
825
+ return { [ONCE]: args.length ? args : true };
826
+ }
827
+ function isOnce(value) {
828
+ return value !== null && typeof value === "object" && ONCE in value;
829
+ }
830
+
440
831
  const RESERVED_PROPS = [
441
832
  "children",
442
833
  "key",
@@ -507,7 +898,7 @@ function getMemoizedPrototype(root) {
507
898
  ctor = new root.constructor();
508
899
  MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
509
900
  }
510
- } catch (e) {
901
+ } catch {
511
902
  }
512
903
  return ctor;
513
904
  }
@@ -538,7 +929,7 @@ function applyProps(object, props) {
538
929
  const rootState = instance && findInitialRoot(instance).getState();
539
930
  const prevHandlers = instance?.eventCount;
540
931
  for (const prop in props) {
541
- let value = props[prop];
932
+ const value = props[prop];
542
933
  if (RESERVED_PROPS.includes(prop)) continue;
543
934
  if (instance && EVENT_REGEX.test(prop)) {
544
935
  if (typeof value === "function") instance.handlers[prop] = value;
@@ -553,6 +944,25 @@ function applyProps(object, props) {
553
944
  continue;
554
945
  }
555
946
  if (value === void 0) continue;
947
+ if (isFromRef(value)) {
948
+ instance?.deferredRefs?.push({ prop, ref: value[FROM_REF] });
949
+ continue;
950
+ }
951
+ if (isOnce(value)) {
952
+ if (instance?.appliedOnce?.has(prop)) continue;
953
+ if (instance) {
954
+ instance.appliedOnce ?? (instance.appliedOnce = /* @__PURE__ */ new Set());
955
+ instance.appliedOnce.add(prop);
956
+ }
957
+ const { root: targetRoot, key: targetKey } = resolve(object, prop);
958
+ const args = value[ONCE];
959
+ if (typeof targetRoot[targetKey] === "function") {
960
+ targetRoot[targetKey](...args === true ? [] : args);
961
+ } else if (args !== true && args.length > 0) {
962
+ targetRoot[targetKey] = args[0];
963
+ }
964
+ continue;
965
+ }
556
966
  let { root, key, target } = resolve(object, prop);
557
967
  if (target === void 0 && (typeof root !== "object" || root === null)) {
558
968
  throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`);
@@ -575,7 +985,7 @@ function applyProps(object, props) {
575
985
  else target.set(value);
576
986
  } else {
577
987
  root[key] = value;
578
- if (rootState && !rootState.linear && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
988
+ if (rootState && rootState.renderer?.outputColorSpace === SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
579
989
  root[key].format === RGBAFormat && root[key].type === UnsignedByteType) {
580
990
  root[key].colorSpace = rootState.textureColorSpace;
581
991
  }
@@ -690,13 +1100,14 @@ function createEvents(store) {
690
1100
  for (const hit of hits) {
691
1101
  let eventObject = hit.object;
692
1102
  while (eventObject) {
693
- if (eventObject.__r3f?.eventCount)
1103
+ if (eventObject.__r3f?.eventCount) {
694
1104
  intersections.push({ ...hit, eventObject });
1105
+ }
695
1106
  eventObject = eventObject.parent;
696
1107
  }
697
1108
  }
698
1109
  if ("pointerId" in event && state.internal.capturedMap.has(event.pointerId)) {
699
- for (let captureData of state.internal.capturedMap.get(event.pointerId).values()) {
1110
+ for (const captureData of state.internal.capturedMap.get(event.pointerId).values()) {
700
1111
  if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
701
1112
  }
702
1113
  }
@@ -726,12 +1137,12 @@ function createEvents(store) {
726
1137
  releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
727
1138
  }
728
1139
  };
729
- let extractEventProps = {};
730
- for (let prop in event) {
731
- let property = event[prop];
1140
+ const extractEventProps = {};
1141
+ for (const prop in event) {
1142
+ const property = event[prop];
732
1143
  if (typeof property !== "function") extractEventProps[prop] = property;
733
1144
  }
734
- let raycastEvent = {
1145
+ const raycastEvent = {
735
1146
  ...hit,
736
1147
  ...extractEventProps,
737
1148
  pointer,
@@ -931,7 +1342,7 @@ function createPointerEvents(store) {
931
1342
  return {
932
1343
  priority: 1,
933
1344
  enabled: true,
934
- compute(event, state, previous) {
1345
+ compute(event, state) {
935
1346
  state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
936
1347
  state.raycaster.setFromCamera(state.pointer, state.camera);
937
1348
  },
@@ -990,331 +1401,57 @@ function notifyDepreciated({ heading, body, link }) {
990
1401
  if (body || link) {
991
1402
  let message = "";
992
1403
  if (body) message += body;
993
- if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
994
- console.warn(`%c${message}`, "font-weight: bold;");
995
- }
996
- }
997
- function getCallerFrame(depth = 3) {
998
- const stack = new Error().stack;
999
- if (!stack) return null;
1000
- const lines = stack.split("\n");
1001
- const frame = lines[depth];
1002
- if (!frame) return null;
1003
- let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
1004
- if (!match) {
1005
- match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
1006
- }
1007
- if (!match) return null;
1008
- const [, fn, url, line] = match;
1009
- return {
1010
- functionName: fn ?? "<anonymous>",
1011
- location: formatLocation(url, Number(line))
1012
- };
1013
- }
1014
- function formatLocation(url, line) {
1015
- const clean = url.split("?")[0];
1016
- const file = clean.split("/").pop() ?? clean;
1017
- return `${file}:${line}`;
1018
- }
1019
- function notifyAlpha({ message, link }) {
1020
- if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
1021
- return;
1022
- }
1023
- if (shownNotices.has(message)) return;
1024
- shownNotices.add(message);
1025
- const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
1026
- console.log(`%c\u{1F52C} ${message}`, boxStyle);
1027
- {
1028
- console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
1029
- }
1030
- }
1031
-
1032
- const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
1033
- const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
1034
- const createStore = (invalidate, advance) => {
1035
- const rootStore = createWithEqualityFn((set, get) => {
1036
- const position = new Vector3();
1037
- const defaultTarget = new Vector3();
1038
- const tempTarget = new Vector3();
1039
- function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
1040
- const { width, height, top, left } = size;
1041
- const aspect = width / height;
1042
- if (target.isVector3) tempTarget.copy(target);
1043
- else tempTarget.set(...target);
1044
- const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
1045
- if (isOrthographicCamera(camera)) {
1046
- return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
1047
- } else {
1048
- const fov = camera.fov * Math.PI / 180;
1049
- const h = 2 * Math.tan(fov / 2) * distance;
1050
- const w = h * (width / height);
1051
- return { width: w, height: h, top, left, factor: width / w, distance, aspect };
1052
- }
1053
- }
1054
- let performanceTimeout = void 0;
1055
- const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
1056
- const pointer = new Vector2();
1057
- const rootState = {
1058
- set,
1059
- get,
1060
- // Mock objects that have to be configured
1061
- gl: null,
1062
- renderer: null,
1063
- camera: null,
1064
- frustum: new Frustum(),
1065
- autoUpdateFrustum: true,
1066
- raycaster: null,
1067
- events: { priority: 1, enabled: true, connected: false },
1068
- scene: null,
1069
- rootScene: null,
1070
- xr: null,
1071
- inspector: null,
1072
- invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
1073
- advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
1074
- legacy: false,
1075
- linear: false,
1076
- flat: false,
1077
- textureColorSpace: "srgb",
1078
- isLegacy: false,
1079
- webGPUSupported: false,
1080
- isNative: false,
1081
- controls: null,
1082
- pointer,
1083
- mouse: pointer,
1084
- frameloop: "always",
1085
- onPointerMissed: void 0,
1086
- onDragOverMissed: void 0,
1087
- onDropMissed: void 0,
1088
- performance: {
1089
- current: 1,
1090
- min: 0.5,
1091
- max: 1,
1092
- debounce: 200,
1093
- regress: () => {
1094
- const state2 = get();
1095
- if (performanceTimeout) clearTimeout(performanceTimeout);
1096
- if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
1097
- performanceTimeout = setTimeout(
1098
- () => setPerformanceCurrent(get().performance.max),
1099
- state2.performance.debounce
1100
- );
1101
- }
1102
- },
1103
- size: { width: 0, height: 0, top: 0, left: 0 },
1104
- viewport: {
1105
- initialDpr: 0,
1106
- dpr: 0,
1107
- width: 0,
1108
- height: 0,
1109
- top: 0,
1110
- left: 0,
1111
- aspect: 0,
1112
- distance: 0,
1113
- factor: 0,
1114
- getCurrentViewport
1115
- },
1116
- setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
1117
- setSize: (width, height, top = 0, left = 0) => {
1118
- const camera = get().camera;
1119
- const size = { width, height, top, left };
1120
- set((state2) => ({ size, viewport: { ...state2.viewport, ...getCurrentViewport(camera, defaultTarget, size) } }));
1121
- },
1122
- setDpr: (dpr) => set((state2) => {
1123
- const resolved = calculateDpr(dpr);
1124
- return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
1125
- }),
1126
- setFrameloop: (frameloop = "always") => {
1127
- set(() => ({ frameloop }));
1128
- },
1129
- setError: (error) => set(() => ({ error })),
1130
- error: null,
1131
- //* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
1132
- uniforms: {},
1133
- nodes: {},
1134
- textures: /* @__PURE__ */ new Map(),
1135
- postProcessing: null,
1136
- passes: {},
1137
- previousRoot: void 0,
1138
- internal: {
1139
- // Events
1140
- interaction: [],
1141
- hovered: /* @__PURE__ */ new Map(),
1142
- subscribers: [],
1143
- initialClick: [0, 0],
1144
- initialHits: [],
1145
- capturedMap: /* @__PURE__ */ new Map(),
1146
- lastEvent: React.createRef(),
1147
- // Visibility tracking (onFramed, onOccluded, onVisible)
1148
- visibilityRegistry: /* @__PURE__ */ new Map(),
1149
- // Occlusion system (WebGPU only)
1150
- occlusionEnabled: false,
1151
- occlusionObserver: null,
1152
- occlusionCache: /* @__PURE__ */ new Map(),
1153
- helperGroup: null,
1154
- // Updates
1155
- active: false,
1156
- frames: 0,
1157
- priority: 0,
1158
- subscribe: (ref, priority, store) => {
1159
- const internal = get().internal;
1160
- internal.priority = internal.priority + (priority > 0 ? 1 : 0);
1161
- internal.subscribers.push({ ref, priority, store });
1162
- internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
1163
- return () => {
1164
- const internal2 = get().internal;
1165
- if (internal2?.subscribers) {
1166
- internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
1167
- internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
1168
- }
1169
- };
1170
- },
1171
- // Renderer Storage (single source of truth)
1172
- actualRenderer: null,
1173
- // Scheduler for useFrameNext (initialized in renderer.tsx)
1174
- scheduler: null
1175
- }
1176
- };
1177
- return rootState;
1178
- });
1179
- const state = rootStore.getState();
1180
- Object.defineProperty(state, "gl", {
1181
- get() {
1182
- const currentState = rootStore.getState();
1183
- if (!currentState.isLegacy && currentState.internal.actualRenderer) {
1184
- const stack = new Error().stack || "";
1185
- const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
1186
- if (!isInternalAccess) {
1187
- const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
1188
- notifyDepreciated({
1189
- heading: "Accessing state.gl in WebGPU mode",
1190
- 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
1191
- });
1192
- }
1193
- }
1194
- return currentState.internal.actualRenderer;
1195
- },
1196
- set(value) {
1197
- rootStore.getState().internal.actualRenderer = value;
1198
- },
1199
- enumerable: true,
1200
- configurable: true
1201
- });
1202
- Object.defineProperty(state, "renderer", {
1203
- get() {
1204
- return rootStore.getState().internal.actualRenderer;
1205
- },
1206
- set(value) {
1207
- rootStore.getState().internal.actualRenderer = value;
1208
- },
1209
- enumerable: true,
1210
- configurable: true
1211
- });
1212
- let oldScene = state.scene;
1213
- rootStore.subscribe(() => {
1214
- const currentState = rootStore.getState();
1215
- const { scene, rootScene, set } = currentState;
1216
- if (scene !== oldScene) {
1217
- oldScene = scene;
1218
- if (scene?.isScene && scene !== rootScene) {
1219
- set({ rootScene: scene });
1220
- }
1221
- }
1222
- });
1223
- let oldSize = state.size;
1224
- let oldDpr = state.viewport.dpr;
1225
- let oldCamera = state.camera;
1226
- rootStore.subscribe(() => {
1227
- const { camera, size, viewport, set, internal } = rootStore.getState();
1228
- const actualRenderer = internal.actualRenderer;
1229
- if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
1230
- oldSize = size;
1231
- oldDpr = viewport.dpr;
1232
- updateCamera(camera, size);
1233
- if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
1234
- const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
1235
- actualRenderer.setSize(size.width, size.height, updateStyle);
1236
- }
1237
- if (camera !== oldCamera) {
1238
- oldCamera = camera;
1239
- const { rootScene } = rootStore.getState();
1240
- if (camera && rootScene && !camera.parent) {
1241
- rootScene.add(camera);
1242
- }
1243
- set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
1244
- const currentState = rootStore.getState();
1245
- if (currentState.autoUpdateFrustum && camera) {
1246
- updateFrustum(camera, currentState.frustum);
1247
- }
1248
- }
1249
- });
1250
- rootStore.subscribe((state2) => invalidate(state2));
1251
- return rootStore;
1252
- };
1253
-
1254
- const memoizedLoaders = /* @__PURE__ */ new WeakMap();
1255
- const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
1256
- function getLoader(Proto) {
1257
- if (isConstructor$1(Proto)) {
1258
- let loader = memoizedLoaders.get(Proto);
1259
- if (!loader) {
1260
- loader = new Proto();
1261
- memoizedLoaders.set(Proto, loader);
1262
- }
1263
- return loader;
1264
- }
1265
- return Proto;
1266
- }
1267
- function loadingFn(extensions, onProgress) {
1268
- return function(Proto, input) {
1269
- const loader = getLoader(Proto);
1270
- if (extensions) extensions(loader);
1271
- if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
1272
- return loader.loadAsync(input, onProgress).then((data) => {
1273
- if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
1274
- return data;
1275
- });
1276
- }
1277
- return new Promise(
1278
- (res, reject) => loader.load(
1279
- input,
1280
- (data) => {
1281
- if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
1282
- res(data);
1283
- },
1284
- onProgress,
1285
- (error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
1286
- )
1287
- );
1404
+ if (link) message += (body ? "\n\n" : "") + `More info: ${link}`;
1405
+ console.warn(`%c${message}`, "font-weight: bold;");
1406
+ }
1407
+ }
1408
+ function getCallerFrame(depth = 3) {
1409
+ const stack = new Error().stack;
1410
+ if (!stack) return null;
1411
+ const lines = stack.split("\n");
1412
+ const frame = lines[depth];
1413
+ if (!frame) return null;
1414
+ let match = frame.match(/^\s*at (?:(.+?) )?\(?(.+?):(\d+):(\d+)\)?$/);
1415
+ if (!match) {
1416
+ match = frame.match(/^(?:(.+?)@)?(.+?):(\d+):(\d+)$/);
1417
+ }
1418
+ if (!match) return null;
1419
+ const [, fn, url, line] = match;
1420
+ return {
1421
+ functionName: fn ?? "<anonymous>",
1422
+ location: formatLocation(url, Number(line))
1288
1423
  };
1289
1424
  }
1290
- function useLoader(loader, input, extensions, onProgress) {
1291
- const keys = Array.isArray(input) ? input : [input];
1292
- const fn = loadingFn(extensions, onProgress);
1293
- const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
1294
- return Array.isArray(input) ? results : results[0];
1425
+ function formatLocation(url, line) {
1426
+ const clean = url.split("?")[0];
1427
+ const file = clean.split("/").pop() ?? clean;
1428
+ return `${file}:${line}`;
1429
+ }
1430
+ function notifyAlpha({ message, link }) {
1431
+ if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
1432
+ return;
1433
+ }
1434
+ if (shownNotices.has(message)) return;
1435
+ shownNotices.add(message);
1436
+ const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
1437
+ console.log(`%c\u{1F52C} ${message}`, boxStyle);
1438
+ {
1439
+ console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
1440
+ }
1295
1441
  }
1296
- useLoader.preload = function(loader, input, extensions, onProgress) {
1297
- const keys = Array.isArray(input) ? input : [input];
1298
- keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
1299
- };
1300
- useLoader.clear = function(loader, input) {
1301
- const keys = Array.isArray(input) ? input : [input];
1302
- keys.forEach((key) => clear([loader, key]));
1303
- };
1304
- useLoader.loader = getLoader;
1305
1442
 
1306
- var __defProp$1 = Object.defineProperty;
1307
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1308
- var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1443
+ var __defProp$2 = Object.defineProperty;
1444
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1445
+ var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1309
1446
  const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
1310
1447
  class PhaseGraph {
1311
1448
  constructor() {
1312
1449
  /** Ordered list of phase nodes */
1313
- __publicField$1(this, "phases", []);
1450
+ __publicField$2(this, "phases", []);
1314
1451
  /** Quick lookup by name */
1315
- __publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
1452
+ __publicField$2(this, "phaseMap", /* @__PURE__ */ new Map());
1316
1453
  /** Cached ordered names (invalidated on changes) */
1317
- __publicField$1(this, "orderedNamesCache", null);
1454
+ __publicField$2(this, "orderedNamesCache", null);
1318
1455
  this.initializeDefaultPhases();
1319
1456
  }
1320
1457
  //* Initialization --------------------------------
@@ -1341,8 +1478,9 @@ class PhaseGraph {
1341
1478
  const node = { name, isAutoGenerated: false };
1342
1479
  let insertIndex = this.phases.length;
1343
1480
  const targetIndex = this.getPhaseIndex(before ?? after);
1344
- if (targetIndex !== -1) insertIndex = before ? targetIndex : targetIndex + 1;
1345
- else {
1481
+ if (targetIndex !== -1) {
1482
+ insertIndex = before ? targetIndex : targetIndex + 1;
1483
+ } else {
1346
1484
  const constraintType = before ? "before" : "after";
1347
1485
  console.warn(`[useFrame] Phase "${before ?? after}" not found for '${constraintType}' constraint`);
1348
1486
  }
@@ -1570,9 +1708,9 @@ function resetJobTiming(job) {
1570
1708
  job.lastRun = void 0;
1571
1709
  }
1572
1710
 
1573
- var __defProp = Object.defineProperty;
1574
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1575
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1711
+ var __defProp$1 = Object.defineProperty;
1712
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1713
+ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1576
1714
  const hmrData = (() => {
1577
1715
  if (typeof process !== "undefined" && process.env.NODE_ENV === "test") return void 0;
1578
1716
  if (typeof import_meta_hot !== "undefined") return import_meta_hot;
@@ -1586,9 +1724,9 @@ const _Scheduler = class _Scheduler {
1586
1724
  //* Constructor ================================
1587
1725
  constructor() {
1588
1726
  //* Critical State ================================
1589
- __publicField(this, "roots", /* @__PURE__ */ new Map());
1590
- __publicField(this, "phaseGraph");
1591
- __publicField(this, "loopState", {
1727
+ __publicField$1(this, "roots", /* @__PURE__ */ new Map());
1728
+ __publicField$1(this, "phaseGraph");
1729
+ __publicField$1(this, "loopState", {
1592
1730
  running: false,
1593
1731
  rafHandle: null,
1594
1732
  lastTime: null,
@@ -1597,21 +1735,21 @@ const _Scheduler = class _Scheduler {
1597
1735
  elapsedTime: 0,
1598
1736
  createdAt: performance.now()
1599
1737
  });
1600
- __publicField(this, "stoppedTime", 0);
1738
+ __publicField$1(this, "stoppedTime", 0);
1601
1739
  //* Private State ================================
1602
- __publicField(this, "nextRootIndex", 0);
1603
- __publicField(this, "globalBeforeJobs", /* @__PURE__ */ new Map());
1604
- __publicField(this, "globalAfterJobs", /* @__PURE__ */ new Map());
1605
- __publicField(this, "nextGlobalIndex", 0);
1606
- __publicField(this, "idleCallbacks", /* @__PURE__ */ new Set());
1607
- __publicField(this, "nextJobIndex", 0);
1608
- __publicField(this, "jobStateListeners", /* @__PURE__ */ new Map());
1609
- __publicField(this, "pendingFrames", 0);
1610
- __publicField(this, "_frameloop", "always");
1740
+ __publicField$1(this, "nextRootIndex", 0);
1741
+ __publicField$1(this, "globalBeforeJobs", /* @__PURE__ */ new Map());
1742
+ __publicField$1(this, "globalAfterJobs", /* @__PURE__ */ new Map());
1743
+ __publicField$1(this, "nextGlobalIndex", 0);
1744
+ __publicField$1(this, "idleCallbacks", /* @__PURE__ */ new Set());
1745
+ __publicField$1(this, "nextJobIndex", 0);
1746
+ __publicField$1(this, "jobStateListeners", /* @__PURE__ */ new Map());
1747
+ __publicField$1(this, "pendingFrames", 0);
1748
+ __publicField$1(this, "_frameloop", "always");
1611
1749
  //* Independent Mode & Error Handling State ================================
1612
- __publicField(this, "_independent", false);
1613
- __publicField(this, "errorHandler", null);
1614
- __publicField(this, "rootReadyCallbacks", /* @__PURE__ */ new Set());
1750
+ __publicField$1(this, "_independent", false);
1751
+ __publicField$1(this, "errorHandler", null);
1752
+ __publicField$1(this, "rootReadyCallbacks", /* @__PURE__ */ new Set());
1615
1753
  //* Core Loop Execution Methods ================================
1616
1754
  /**
1617
1755
  * Main RAF loop callback.
@@ -1620,7 +1758,7 @@ const _Scheduler = class _Scheduler {
1620
1758
  * @returns {void}
1621
1759
  * @private
1622
1760
  */
1623
- __publicField(this, "loop", (timestamp) => {
1761
+ __publicField$1(this, "loop", (timestamp) => {
1624
1762
  if (!this.loopState.running) return;
1625
1763
  this.executeFrame(timestamp);
1626
1764
  if (this._frameloop === "demand") {
@@ -2323,16 +2461,329 @@ const _Scheduler = class _Scheduler {
2323
2461
  return /* @__PURE__ */ new Set([value]);
2324
2462
  }
2325
2463
  };
2326
- //* Static State & Methods (Singleton Usage) ================================
2327
- //* Cross-Bundle Singleton Key ==============================
2328
- // Use Symbol.for() to ensure scheduler is shared across bundle boundaries
2329
- // This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
2330
- __publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
2331
- let Scheduler = _Scheduler;
2332
- const getScheduler = () => Scheduler.get();
2333
- if (hmrData) {
2334
- hmrData.accept?.();
2464
+ //* Static State & Methods (Singleton Usage) ================================
2465
+ //* Cross-Bundle Singleton Key ==============================
2466
+ // Use Symbol.for() to ensure scheduler is shared across bundle boundaries
2467
+ // This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
2468
+ __publicField$1(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
2469
+ let Scheduler = _Scheduler;
2470
+ const getScheduler = () => Scheduler.get();
2471
+ if (hmrData) {
2472
+ hmrData.accept?.();
2473
+ }
2474
+
2475
+ const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
2476
+ const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
2477
+ const createStore = (invalidate, advance) => {
2478
+ const rootStore = createWithEqualityFn((set, get) => {
2479
+ const position = new Vector3();
2480
+ const defaultTarget = new Vector3();
2481
+ const tempTarget = new Vector3();
2482
+ function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
2483
+ const { width, height, top, left } = size;
2484
+ const aspect = width / height;
2485
+ if (target.isVector3) tempTarget.copy(target);
2486
+ else tempTarget.set(...target);
2487
+ const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
2488
+ if (isOrthographicCamera(camera)) {
2489
+ return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
2490
+ } else {
2491
+ const fov = camera.fov * Math.PI / 180;
2492
+ const h = 2 * Math.tan(fov / 2) * distance;
2493
+ const w = h * (width / height);
2494
+ return { width: w, height: h, top, left, factor: width / w, distance, aspect };
2495
+ }
2496
+ }
2497
+ let performanceTimeout = void 0;
2498
+ const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
2499
+ const pointer = new Vector2();
2500
+ const rootState = {
2501
+ set,
2502
+ get,
2503
+ // Mock objects that have to be configured
2504
+ // primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
2505
+ primaryStore: null,
2506
+ gl: null,
2507
+ renderer: null,
2508
+ camera: null,
2509
+ frustum: new Frustum(),
2510
+ autoUpdateFrustum: true,
2511
+ raycaster: null,
2512
+ events: { priority: 1, enabled: true, connected: false },
2513
+ scene: null,
2514
+ rootScene: null,
2515
+ xr: null,
2516
+ inspector: null,
2517
+ invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
2518
+ advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
2519
+ textureColorSpace: SRGBColorSpace,
2520
+ isLegacy: false,
2521
+ webGPUSupported: false,
2522
+ isNative: false,
2523
+ controls: null,
2524
+ pointer,
2525
+ mouse: pointer,
2526
+ frameloop: "always",
2527
+ onPointerMissed: void 0,
2528
+ onDragOverMissed: void 0,
2529
+ onDropMissed: void 0,
2530
+ performance: {
2531
+ current: 1,
2532
+ min: 0.5,
2533
+ max: 1,
2534
+ debounce: 200,
2535
+ regress: () => {
2536
+ const state2 = get();
2537
+ if (performanceTimeout) clearTimeout(performanceTimeout);
2538
+ if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
2539
+ performanceTimeout = setTimeout(
2540
+ () => setPerformanceCurrent(get().performance.max),
2541
+ state2.performance.debounce
2542
+ );
2543
+ }
2544
+ },
2545
+ size: { width: 0, height: 0, top: 0, left: 0 },
2546
+ viewport: {
2547
+ initialDpr: 0,
2548
+ dpr: 0,
2549
+ width: 0,
2550
+ height: 0,
2551
+ top: 0,
2552
+ left: 0,
2553
+ aspect: 0,
2554
+ distance: 0,
2555
+ factor: 0,
2556
+ getCurrentViewport
2557
+ },
2558
+ setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
2559
+ setSize: (width, height, top, left) => {
2560
+ const state2 = get();
2561
+ if (width === void 0) {
2562
+ set({ _sizeImperative: false });
2563
+ if (state2._sizeProps) {
2564
+ const { width: propW, height: propH } = state2._sizeProps;
2565
+ if (propW !== void 0 || propH !== void 0) {
2566
+ const currentSize = state2.size;
2567
+ const newSize = {
2568
+ width: propW ?? currentSize.width,
2569
+ height: propH ?? currentSize.height,
2570
+ top: currentSize.top,
2571
+ left: currentSize.left
2572
+ };
2573
+ set((s) => ({
2574
+ size: newSize,
2575
+ viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
2576
+ }));
2577
+ getScheduler().invalidate();
2578
+ }
2579
+ }
2580
+ return;
2581
+ }
2582
+ const w = width;
2583
+ const h = height ?? width;
2584
+ const t = top ?? state2.size.top;
2585
+ const l = left ?? state2.size.left;
2586
+ const size = { width: w, height: h, top: t, left: l };
2587
+ set((s) => ({
2588
+ size,
2589
+ viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
2590
+ _sizeImperative: true
2591
+ }));
2592
+ getScheduler().invalidate();
2593
+ },
2594
+ setDpr: (dpr) => set((state2) => {
2595
+ const resolved = calculateDpr(dpr);
2596
+ return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
2597
+ }),
2598
+ setFrameloop: (frameloop = "always") => {
2599
+ set(() => ({ frameloop }));
2600
+ },
2601
+ setError: (error) => set(() => ({ error })),
2602
+ error: null,
2603
+ //* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
2604
+ uniforms: {},
2605
+ nodes: {},
2606
+ textures: /* @__PURE__ */ new Map(),
2607
+ postProcessing: null,
2608
+ passes: {},
2609
+ _hmrVersion: 0,
2610
+ _sizeImperative: false,
2611
+ _sizeProps: null,
2612
+ previousRoot: void 0,
2613
+ internal: {
2614
+ // Events
2615
+ interaction: [],
2616
+ hovered: /* @__PURE__ */ new Map(),
2617
+ subscribers: [],
2618
+ initialClick: [0, 0],
2619
+ initialHits: [],
2620
+ capturedMap: /* @__PURE__ */ new Map(),
2621
+ lastEvent: React.createRef(),
2622
+ // Visibility tracking (onFramed, onOccluded, onVisible)
2623
+ visibilityRegistry: /* @__PURE__ */ new Map(),
2624
+ // Occlusion system (WebGPU only)
2625
+ occlusionEnabled: false,
2626
+ occlusionObserver: null,
2627
+ occlusionCache: /* @__PURE__ */ new Map(),
2628
+ helperGroup: null,
2629
+ // Updates
2630
+ active: false,
2631
+ frames: 0,
2632
+ priority: 0,
2633
+ subscribe: (ref, priority, store) => {
2634
+ const internal = get().internal;
2635
+ internal.priority = internal.priority + (priority > 0 ? 1 : 0);
2636
+ internal.subscribers.push({ ref, priority, store });
2637
+ internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
2638
+ return () => {
2639
+ const internal2 = get().internal;
2640
+ if (internal2?.subscribers) {
2641
+ internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
2642
+ internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
2643
+ }
2644
+ };
2645
+ },
2646
+ // Renderer Storage (single source of truth)
2647
+ actualRenderer: null,
2648
+ // Scheduler for useFrameNext (initialized in renderer.tsx)
2649
+ scheduler: null
2650
+ }
2651
+ };
2652
+ return rootState;
2653
+ });
2654
+ const state = rootStore.getState();
2655
+ Object.defineProperty(state, "gl", {
2656
+ get() {
2657
+ const currentState = rootStore.getState();
2658
+ if (!currentState.isLegacy && currentState.internal.actualRenderer) {
2659
+ const stack = new Error().stack || "";
2660
+ const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
2661
+ if (!isInternalAccess) {
2662
+ const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
2663
+ notifyDepreciated({
2664
+ heading: "Accessing state.gl in WebGPU mode",
2665
+ 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
2666
+ });
2667
+ }
2668
+ }
2669
+ return currentState.internal.actualRenderer;
2670
+ },
2671
+ set(value) {
2672
+ rootStore.getState().internal.actualRenderer = value;
2673
+ },
2674
+ enumerable: true,
2675
+ configurable: true
2676
+ });
2677
+ Object.defineProperty(state, "renderer", {
2678
+ get() {
2679
+ return rootStore.getState().internal.actualRenderer;
2680
+ },
2681
+ set(value) {
2682
+ rootStore.getState().internal.actualRenderer = value;
2683
+ },
2684
+ enumerable: true,
2685
+ configurable: true
2686
+ });
2687
+ let oldScene = state.scene;
2688
+ rootStore.subscribe(() => {
2689
+ const currentState = rootStore.getState();
2690
+ const { scene, rootScene, set } = currentState;
2691
+ if (scene !== oldScene) {
2692
+ oldScene = scene;
2693
+ if (scene?.isScene && scene !== rootScene) {
2694
+ set({ rootScene: scene });
2695
+ }
2696
+ }
2697
+ });
2698
+ let oldSize = state.size;
2699
+ let oldDpr = state.viewport.dpr;
2700
+ let oldCamera = state.camera;
2701
+ rootStore.subscribe(() => {
2702
+ const { camera, size, viewport, set, internal } = rootStore.getState();
2703
+ const actualRenderer = internal.actualRenderer;
2704
+ const canvasTarget = internal.canvasTarget;
2705
+ if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
2706
+ oldSize = size;
2707
+ oldDpr = viewport.dpr;
2708
+ updateCamera(camera, size);
2709
+ if (canvasTarget) {
2710
+ if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
2711
+ const updateStyle = typeof HTMLCanvasElement !== "undefined" && canvasTarget.domElement instanceof HTMLCanvasElement;
2712
+ canvasTarget.setSize(size.width, size.height, updateStyle);
2713
+ } else {
2714
+ if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
2715
+ const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
2716
+ actualRenderer.setSize(size.width, size.height, updateStyle);
2717
+ }
2718
+ }
2719
+ if (camera !== oldCamera) {
2720
+ oldCamera = camera;
2721
+ const { rootScene } = rootStore.getState();
2722
+ if (camera && rootScene && !camera.parent) {
2723
+ rootScene.add(camera);
2724
+ }
2725
+ set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
2726
+ const currentState = rootStore.getState();
2727
+ if (currentState.autoUpdateFrustum && camera) {
2728
+ updateFrustum(camera, currentState.frustum);
2729
+ }
2730
+ }
2731
+ });
2732
+ rootStore.subscribe((state2) => invalidate(state2));
2733
+ return rootStore;
2734
+ };
2735
+
2736
+ const memoizedLoaders = /* @__PURE__ */ new WeakMap();
2737
+ const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
2738
+ function getLoader(Proto) {
2739
+ if (isConstructor$1(Proto)) {
2740
+ let loader = memoizedLoaders.get(Proto);
2741
+ if (!loader) {
2742
+ loader = new Proto();
2743
+ memoizedLoaders.set(Proto, loader);
2744
+ }
2745
+ return loader;
2746
+ }
2747
+ return Proto;
2748
+ }
2749
+ function loadingFn(extensions, onProgress) {
2750
+ return function(Proto, input) {
2751
+ const loader = getLoader(Proto);
2752
+ if (extensions) extensions(loader);
2753
+ if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
2754
+ return loader.loadAsync(input, onProgress).then((data) => {
2755
+ if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
2756
+ return data;
2757
+ });
2758
+ }
2759
+ return new Promise(
2760
+ (res, reject) => loader.load(
2761
+ input,
2762
+ (data) => {
2763
+ if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
2764
+ res(data);
2765
+ },
2766
+ onProgress,
2767
+ (error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
2768
+ )
2769
+ );
2770
+ };
2771
+ }
2772
+ function useLoader(loader, input, extensions, onProgress) {
2773
+ const keys = Array.isArray(input) ? input : [input];
2774
+ const fn = loadingFn(extensions, onProgress);
2775
+ const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
2776
+ return Array.isArray(input) ? results : results[0];
2335
2777
  }
2778
+ useLoader.preload = function(loader, input, extensions, onProgress) {
2779
+ const keys = Array.isArray(input) ? input : [input];
2780
+ keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
2781
+ };
2782
+ useLoader.clear = function(loader, input) {
2783
+ const keys = Array.isArray(input) ? input : [input];
2784
+ keys.forEach((key) => clear([loader, key]));
2785
+ };
2786
+ useLoader.loader = getLoader;
2336
2787
 
2337
2788
  function useFrame(callback, priorityOrOptions) {
2338
2789
  const store = React.useContext(context);
@@ -2513,6 +2964,9 @@ function useTexture(input, optionsOrOnLoad) {
2513
2964
  const textureCache = useThree((state) => state.textures);
2514
2965
  const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
2515
2966
  const { onLoad, cache = false } = options;
2967
+ const onLoadRef = useRef(onLoad);
2968
+ onLoadRef.current = onLoad;
2969
+ const onLoadCalledForRef = useRef(null);
2516
2970
  const urls = useMemo(() => getUrls(input), [input]);
2517
2971
  const cachedResult = useMemo(() => {
2518
2972
  if (!cache) return null;
@@ -2523,9 +2977,13 @@ function useTexture(input, optionsOrOnLoad) {
2523
2977
  TextureLoader,
2524
2978
  IsObject(input) ? Object.values(input) : input
2525
2979
  );
2980
+ const inputKey = urls.join("\0");
2526
2981
  useLayoutEffect(() => {
2527
- if (!cachedResult) onLoad?.(loadedTextures);
2528
- }, [onLoad, cachedResult, loadedTextures]);
2982
+ if (cachedResult) return;
2983
+ if (onLoadCalledForRef.current === inputKey) return;
2984
+ onLoadCalledForRef.current = inputKey;
2985
+ onLoadRef.current?.(loadedTextures);
2986
+ }, [cachedResult, loadedTextures, inputKey]);
2529
2987
  useEffect(() => {
2530
2988
  if (cachedResult) return;
2531
2989
  if ("initTexture" in renderer) {
@@ -2692,14 +3150,31 @@ function useTextures() {
2692
3150
  }, [store]);
2693
3151
  }
2694
3152
 
2695
- function useRenderTarget(width, height, options) {
3153
+ function useRenderTarget(widthOrOptions, heightOrOptions, options) {
2696
3154
  const isLegacy = useThree((s) => s.isLegacy);
2697
3155
  const size = useThree((s) => s.size);
3156
+ let width;
3157
+ let height;
3158
+ let opts;
3159
+ if (typeof widthOrOptions === "object") {
3160
+ opts = widthOrOptions;
3161
+ } else if (typeof widthOrOptions === "number") {
3162
+ width = widthOrOptions;
3163
+ if (typeof heightOrOptions === "object") {
3164
+ height = widthOrOptions;
3165
+ opts = heightOrOptions;
3166
+ } else if (typeof heightOrOptions === "number") {
3167
+ height = heightOrOptions;
3168
+ opts = options;
3169
+ } else {
3170
+ height = widthOrOptions;
3171
+ }
3172
+ }
2698
3173
  return useMemo(() => {
2699
3174
  const w = width ?? size.width;
2700
3175
  const h = height ?? size.height;
2701
- return new RenderTarget(w, h, options);
2702
- }, [width, height, size.width, size.height, options, isLegacy]);
3176
+ return new RenderTarget(w, h, opts);
3177
+ }, [width, height, size.width, size.height, opts, isLegacy]);
2703
3178
  }
2704
3179
 
2705
3180
  function useStore() {
@@ -2749,28 +3224,18 @@ function addTail(callback) {
2749
3224
  function invalidate(state, frames = 1, stackFrames = false) {
2750
3225
  getScheduler().invalidate(frames, stackFrames);
2751
3226
  }
2752
- function advance(timestamp, runGlobalEffects = true, state, frame) {
3227
+ function advance(timestamp) {
2753
3228
  getScheduler().step(timestamp);
2754
3229
  }
2755
3230
 
2756
- const version = "10.0.0-alpha.1";
3231
+ const version = "10.0.0-alpha.2";
2757
3232
  const packageData = {
2758
3233
  version: version};
2759
3234
 
2760
3235
  function Xb(Tt) {
2761
3236
  return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
2762
3237
  }
2763
- var Rm = { exports: {} }, Og = { exports: {} };
2764
- /**
2765
- * @license React
2766
- * react-reconciler.production.js
2767
- *
2768
- * Copyright (c) Meta Platforms, Inc. and affiliates.
2769
- *
2770
- * This source code is licensed under the MIT license found in the
2771
- * LICENSE file in the root directory of this source tree.
2772
- */
2773
- var _b;
3238
+ var Rm = { exports: {} }, Og = { exports: {} }, _b;
2774
3239
  function Kb() {
2775
3240
  return _b || (_b = 1, (function(Tt) {
2776
3241
  Tt.exports = function(m) {
@@ -3842,7 +4307,6 @@ Error generating stack: ` + l.message + `
3842
4307
  if (J === cl || J === jc) throw J;
3843
4308
  var Ge = Yn(29, J, null, P.mode);
3844
4309
  return Ge.lanes = H, Ge.return = P, Ge;
3845
- } finally {
3846
4310
  }
3847
4311
  };
3848
4312
  }
@@ -4496,7 +4960,6 @@ Error generating stack: ` + l.message + `
4496
4960
  var h = r.lastRenderedState, y = d(h, a);
4497
4961
  if (c.hasEagerState = true, c.eagerState = y, jn(y, h)) return go(t, r, c, 0), Ne === null && Bn(), false;
4498
4962
  } catch {
4499
- } finally {
4500
4963
  }
4501
4964
  if (a = yo(t, r, c, l), a !== null) return nt(a, t, l), ns(a, r, l), true;
4502
4965
  }
@@ -6917,10 +7380,7 @@ Error generating stack: ` + l.message + `
6917
7380
  function vr(t, r) {
6918
7381
  Sf(t, r), (t = t.alternate) && Sf(t, r);
6919
7382
  }
6920
- var ie = {}, Fm = React__default, tt = Tb, Lt = Object.assign, hc = Symbol.for("react.element"), zs = Symbol.for("react.transitional.element"), sa = Symbol.for("react.portal"), $a = Symbol.for("react.fragment"), kf = Symbol.for("react.strict_mode"), Cs = Symbol.for("react.profiler"), mc = Symbol.for("react.consumer"), Io = Symbol.for("react.context"), Zi = Symbol.for("react.forward_ref"), Va = Symbol.for("react.suspense"), Te = Symbol.for("react.suspense_list"), wf = Symbol.for("react.memo"), ua = Symbol.for("react.lazy");
6921
- var gc = Symbol.for("react.activity");
6922
- var $r = Symbol.for("react.memo_cache_sentinel");
6923
- var Pf = Symbol.iterator, xf = Symbol.for("react.client.reference"), ca = Array.isArray, M = Fm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Yp = m.rendererVersion, zf = m.rendererPackageName, Cf = m.extraDevToolsConfig, Ts = m.getPublicInstance, Hm = m.getRootHostContext, Xp = m.getChildHostContext, Am = m.prepareForCommit, _s = m.resetAfterCommit, Vr = m.createInstance;
7383
+ var ie = {}, Fm = React__default, tt = Tb, Lt = Object.assign, hc = Symbol.for("react.element"), zs = Symbol.for("react.transitional.element"), sa = Symbol.for("react.portal"), $a = Symbol.for("react.fragment"), kf = Symbol.for("react.strict_mode"), Cs = Symbol.for("react.profiler"), mc = Symbol.for("react.consumer"), Io = Symbol.for("react.context"), Zi = Symbol.for("react.forward_ref"), Va = Symbol.for("react.suspense"), Te = Symbol.for("react.suspense_list"), wf = Symbol.for("react.memo"), ua = Symbol.for("react.lazy"), gc = Symbol.for("react.activity"), $r = Symbol.for("react.memo_cache_sentinel"), Pf = Symbol.iterator, xf = Symbol.for("react.client.reference"), ca = Array.isArray, M = Fm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Yp = m.rendererVersion, zf = m.rendererPackageName, Cf = m.extraDevToolsConfig, Ts = m.getPublicInstance, Hm = m.getRootHostContext, Xp = m.getChildHostContext, Am = m.prepareForCommit, _s = m.resetAfterCommit, Vr = m.createInstance;
6924
7384
  m.cloneMutableInstance;
6925
7385
  var yc = m.appendInitialChild, Kp = m.finalizeInitialChildren, Rs = m.shouldSetTextContent, bc = m.createTextInstance;
6926
7386
  m.cloneMutableTextInstance;
@@ -7289,17 +7749,7 @@ No matching component was found for:
7289
7749
  }, Tt.exports.default = Tt.exports, Object.defineProperty(Tt.exports, "__esModule", { value: true });
7290
7750
  })(Og)), Og.exports;
7291
7751
  }
7292
- var Mg = { exports: {} };
7293
- /**
7294
- * @license React
7295
- * react-reconciler.development.js
7296
- *
7297
- * Copyright (c) Meta Platforms, Inc. and affiliates.
7298
- *
7299
- * This source code is licensed under the MIT license found in the
7300
- * LICENSE file in the root directory of this source tree.
7301
- */
7302
- var Rb;
7752
+ var Mg = { exports: {} }, Rb;
7303
7753
  function e0() {
7304
7754
  return Rb || (Rb = 1, (function(Tt) {
7305
7755
  process.env.NODE_ENV !== "production" && (Tt.exports = function(m) {
@@ -13066,10 +13516,7 @@ Check the render method of %s.`, G(di) || "Unknown")), i = zo(n), i.payload = {
13066
13516
  function Ic() {
13067
13517
  return di;
13068
13518
  }
13069
- var le = {}, qm = React__default, St = Tb, ze = Object.assign, Uh = Symbol.for("react.element"), Ho = Symbol.for("react.transitional.element"), Ao = Symbol.for("react.portal"), ol = Symbol.for("react.fragment"), Lc = Symbol.for("react.strict_mode"), Uf = Symbol.for("react.profiler"), ei = Symbol.for("react.consumer"), on = Symbol.for("react.context"), jn = Symbol.for("react.forward_ref"), Nc = Symbol.for("react.suspense"), Bf = Symbol.for("react.suspense_list"), al = Symbol.for("react.memo"), kt = Symbol.for("react.lazy");
13070
- var Ds = Symbol.for("react.activity");
13071
- var Bh = Symbol.for("react.memo_cache_sentinel");
13072
- var ni = Symbol.iterator, il = Symbol.for("react.client.reference"), fn = Array.isArray, x = qm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Jt = m.rendererVersion, Zt = m.rendererPackageName, jo = m.extraDevToolsConfig, ot = m.getPublicInstance, Zr = m.getRootHostContext, Dn = m.getChildHostContext, Ws = m.prepareForCommit, pa = m.resetAfterCommit, Fc = m.createInstance;
13519
+ var le = {}, qm = React__default, St = Tb, ze = Object.assign, Uh = Symbol.for("react.element"), Ho = Symbol.for("react.transitional.element"), Ao = Symbol.for("react.portal"), ol = Symbol.for("react.fragment"), Lc = Symbol.for("react.strict_mode"), Uf = Symbol.for("react.profiler"), ei = Symbol.for("react.consumer"), on = Symbol.for("react.context"), jn = Symbol.for("react.forward_ref"), Nc = Symbol.for("react.suspense"), Bf = Symbol.for("react.suspense_list"), al = Symbol.for("react.memo"), kt = Symbol.for("react.lazy"), Ds = Symbol.for("react.activity"), Bh = Symbol.for("react.memo_cache_sentinel"), ni = Symbol.iterator, il = Symbol.for("react.client.reference"), fn = Array.isArray, x = qm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Jt = m.rendererVersion, Zt = m.rendererPackageName, jo = m.extraDevToolsConfig, ot = m.getPublicInstance, Zr = m.getRootHostContext, Dn = m.getChildHostContext, Ws = m.prepareForCommit, pa = m.resetAfterCommit, Fc = m.createInstance;
13073
13520
  m.cloneMutableInstance;
13074
13521
  var bn = m.appendInitialChild, Ue = m.finalizeInitialChildren, ue = m.shouldSetTextContent, Do = m.createTextInstance;
13075
13522
  m.cloneMutableTextInstance;
@@ -14037,15 +14484,6 @@ function n0() {
14037
14484
  var t0 = n0();
14038
14485
  const r0 = Xb(t0);
14039
14486
 
14040
- /**
14041
- * @license React
14042
- * react-reconciler-constants.production.js
14043
- *
14044
- * Copyright (c) Meta Platforms, Inc. and affiliates.
14045
- *
14046
- * This source code is licensed under the MIT license found in the
14047
- * LICENSE file in the root directory of this source tree.
14048
- */
14049
14487
  const t = 1, o = 8, r = 32, e = 2;
14050
14488
 
14051
14489
  function createReconciler(config) {
@@ -14072,10 +14510,11 @@ function extend(objects) {
14072
14510
  function validateInstance(type, props) {
14073
14511
  const name = toPascalCase(type);
14074
14512
  const target = catalogue[name];
14075
- if (type !== "primitive" && !target)
14513
+ if (type !== "primitive" && !target) {
14076
14514
  throw new Error(
14077
14515
  `R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`
14078
14516
  );
14517
+ }
14079
14518
  if (type === "primitive" && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`);
14080
14519
  if (props.args !== void 0 && !Array.isArray(props.args)) throw new Error("R3F: The args prop must be an array!");
14081
14520
  }
@@ -14239,6 +14678,7 @@ function swapInstances() {
14239
14678
  instance.object = instance.props.object ?? new target(...instance.props.args ?? []);
14240
14679
  instance.object.__r3f = instance;
14241
14680
  setFiberRef(fiber, instance.object);
14681
+ delete instance.appliedOnce;
14242
14682
  applyProps(instance.object, instance.props);
14243
14683
  if (instance.props.attach) {
14244
14684
  attach(parent, instance);
@@ -14312,8 +14752,22 @@ const reconciler = /* @__PURE__ */ createReconciler({
14312
14752
  const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
14313
14753
  if (isTailSibling) swapInstances();
14314
14754
  },
14315
- finalizeInitialChildren: () => false,
14316
- commitMount() {
14755
+ finalizeInitialChildren: (instance) => {
14756
+ for (const prop in instance.props) {
14757
+ if (isFromRef(instance.props[prop])) return true;
14758
+ }
14759
+ return false;
14760
+ },
14761
+ commitMount(instance) {
14762
+ const resolved = {};
14763
+ for (const prop in instance.props) {
14764
+ const value = instance.props[prop];
14765
+ if (isFromRef(value)) {
14766
+ const ref = value[FROM_REF];
14767
+ if (ref.current != null) resolved[prop] = ref.current;
14768
+ }
14769
+ }
14770
+ if (Object.keys(resolved).length) applyProps(instance.object, resolved);
14317
14771
  },
14318
14772
  getPublicInstance: (instance) => instance?.object,
14319
14773
  prepareForCommit: () => null,
@@ -14526,14 +14980,17 @@ function createRoot(canvas) {
14526
14980
  if (!prevRoot) _roots.set(canvas, { fiber, store });
14527
14981
  let onCreated;
14528
14982
  let lastCamera;
14529
- let lastConfiguredProps = {};
14983
+ const lastConfiguredProps = {};
14530
14984
  let configured = false;
14531
14985
  let pending = null;
14532
14986
  return {
14533
14987
  async configure(props = {}) {
14534
14988
  let resolve;
14535
14989
  pending = new Promise((_resolve) => resolve = _resolve);
14536
- let {
14990
+ const {
14991
+ id: canvasId,
14992
+ primaryCanvas,
14993
+ scheduler: schedulerConfig,
14537
14994
  gl: glConfig,
14538
14995
  renderer: rendererConfig,
14539
14996
  size: propsSize,
@@ -14541,10 +14998,7 @@ function createRoot(canvas) {
14541
14998
  events,
14542
14999
  onCreated: onCreatedCallback,
14543
15000
  shadows = false,
14544
- linear = false,
14545
- flat = false,
14546
15001
  textureColorSpace = SRGBColorSpace,
14547
- legacy = false,
14548
15002
  orthographic = false,
14549
15003
  frameloop = "always",
14550
15004
  dpr = [1, 2],
@@ -14555,11 +15009,14 @@ function createRoot(canvas) {
14555
15009
  onDragOverMissed,
14556
15010
  onDropMissed,
14557
15011
  autoUpdateFrustum = true,
14558
- occlusion = false
15012
+ occlusion = false,
15013
+ _sizeProps,
15014
+ forceEven
14559
15015
  } = props;
14560
- let state = store.getState();
15016
+ const state = store.getState();
14561
15017
  const defaultGPUProps = {
14562
- canvas
15018
+ canvas,
15019
+ antialias: true
14563
15020
  };
14564
15021
  if (glConfig && !R3F_BUILD_LEGACY) {
14565
15022
  throw new Error(
@@ -14570,7 +15027,27 @@ function createRoot(canvas) {
14570
15027
  throw new Error("Cannot use both gl and renderer props at the same time");
14571
15028
  }
14572
15029
  let renderer = state.internal.actualRenderer;
14573
- if (!state.internal.actualRenderer) {
15030
+ if (primaryCanvas && !state.internal.actualRenderer) {
15031
+ const primary = await waitForPrimary(primaryCanvas);
15032
+ renderer = primary.renderer;
15033
+ state.internal.actualRenderer = renderer;
15034
+ const canvasTarget = new CanvasTarget(canvas);
15035
+ primary.store.setState((prev) => ({
15036
+ internal: { ...prev.internal, isMultiCanvas: true }
15037
+ }));
15038
+ state.set((prev) => ({
15039
+ webGPUSupported: primary.store.getState().webGPUSupported,
15040
+ renderer,
15041
+ primaryStore: primary.store,
15042
+ internal: {
15043
+ ...prev.internal,
15044
+ canvasTarget,
15045
+ isMultiCanvas: true,
15046
+ isSecondary: true,
15047
+ targetId: primaryCanvas
15048
+ }
15049
+ }));
15050
+ } else if (!state.internal.actualRenderer) {
14574
15051
  renderer = await resolveRenderer(rendererConfig, defaultGPUProps, WebGPURenderer);
14575
15052
  if (!renderer.hasInitialized?.()) {
14576
15053
  await renderer.init();
@@ -14578,14 +15055,27 @@ function createRoot(canvas) {
14578
15055
  const backend = renderer.backend;
14579
15056
  const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
14580
15057
  state.internal.actualRenderer = renderer;
14581
- state.set({ webGPUSupported: isWebGPUBackend, renderer });
15058
+ state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
15059
+ if (canvasId && !state.internal.isSecondary) {
15060
+ const canvasTarget = new CanvasTarget(canvas);
15061
+ const unregisterPrimary = registerPrimary(canvasId, renderer, store);
15062
+ state.set((prev) => ({
15063
+ internal: {
15064
+ ...prev.internal,
15065
+ canvasTarget,
15066
+ unregisterPrimary
15067
+ }
15068
+ }));
15069
+ }
14582
15070
  }
14583
15071
  let raycaster = state.raycaster;
14584
15072
  if (!raycaster) state.set({ raycaster: raycaster = new Raycaster() });
14585
15073
  const { params, ...options } = raycastOptions || {};
14586
15074
  if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options });
14587
- if (!is.equ(params, raycaster.params, shallowLoose))
15075
+ if (!is.equ(params, raycaster.params, shallowLoose)) {
14588
15076
  applyProps(raycaster, { params: { ...raycaster.params, ...params } });
15077
+ }
15078
+ let tempCamera = state.camera;
14589
15079
  if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
14590
15080
  lastCamera = cameraOptions;
14591
15081
  const isCamera = cameraOptions?.isCamera;
@@ -14605,6 +15095,7 @@ function createRoot(canvas) {
14605
15095
  if (!state.camera && !cameraOptions?.rotation) camera.lookAt(0, 0, 0);
14606
15096
  }
14607
15097
  state.set({ camera });
15098
+ tempCamera = camera;
14608
15099
  raycaster.camera = camera;
14609
15100
  }
14610
15101
  if (!state.scene) {
@@ -14622,7 +15113,7 @@ function createRoot(canvas) {
14622
15113
  rootScene: scene,
14623
15114
  internal: { ...prev.internal, container: scene }
14624
15115
  }));
14625
- const camera = state.camera;
15116
+ const camera = tempCamera;
14626
15117
  if (camera && !camera.parent) scene.add(camera);
14627
15118
  }
14628
15119
  if (events && !state.events.handlers) {
@@ -14636,9 +15127,17 @@ function createRoot(canvas) {
14636
15127
  wasEnabled = enabled;
14637
15128
  });
14638
15129
  }
15130
+ if (_sizeProps !== void 0) {
15131
+ state.set({ _sizeProps });
15132
+ }
15133
+ if (forceEven !== void 0 && state.internal.forceEven !== forceEven) {
15134
+ state.set((prev) => ({ internal: { ...prev.internal, forceEven } }));
15135
+ }
14639
15136
  const size = computeInitialSize(canvas, propsSize);
14640
- if (!is.equ(size, state.size, shallowLoose)) {
15137
+ if (!state._sizeImperative && !is.equ(size, state.size, shallowLoose)) {
15138
+ const wasImperative = state._sizeImperative;
14641
15139
  state.setSize(size.width, size.height, size.top, size.left);
15140
+ if (!wasImperative) state.set({ _sizeImperative: false });
14642
15141
  }
14643
15142
  if (dpr !== void 0 && !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose)) {
14644
15143
  state.setDpr(dpr);
@@ -14663,7 +15162,7 @@ function createRoot(canvas) {
14663
15162
  const handleXRFrame = (timestamp, frame) => {
14664
15163
  const state2 = store.getState();
14665
15164
  if (state2.frameloop === "never") return;
14666
- advance(timestamp, true);
15165
+ advance(timestamp);
14667
15166
  };
14668
15167
  const actualRenderer = state.internal.actualRenderer;
14669
15168
  const handleSessionChange = () => {
@@ -14675,16 +15174,16 @@ function createRoot(canvas) {
14675
15174
  };
14676
15175
  const xr = {
14677
15176
  connect() {
14678
- const { gl, renderer: renderer2, isLegacy } = store.getState();
14679
- const actualRenderer2 = renderer2 || gl;
14680
- actualRenderer2.xr.addEventListener("sessionstart", handleSessionChange);
14681
- actualRenderer2.xr.addEventListener("sessionend", handleSessionChange);
15177
+ const { gl, renderer: renderer2 } = store.getState();
15178
+ const xrManager = (renderer2 || gl).xr;
15179
+ xrManager.addEventListener("sessionstart", handleSessionChange);
15180
+ xrManager.addEventListener("sessionend", handleSessionChange);
14682
15181
  },
14683
15182
  disconnect() {
14684
- const { gl, renderer: renderer2, isLegacy } = store.getState();
14685
- const actualRenderer2 = renderer2 || gl;
14686
- actualRenderer2.xr.removeEventListener("sessionstart", handleSessionChange);
14687
- actualRenderer2.xr.removeEventListener("sessionend", handleSessionChange);
15183
+ const { gl, renderer: renderer2 } = store.getState();
15184
+ const xrManager = (renderer2 || gl).xr;
15185
+ xrManager.removeEventListener("sessionstart", handleSessionChange);
15186
+ xrManager.removeEventListener("sessionend", handleSessionChange);
14688
15187
  }
14689
15188
  };
14690
15189
  if (typeof renderer.xr?.addEventListener === "function") xr.connect();
@@ -14708,15 +15207,21 @@ function createRoot(canvas) {
14708
15207
  } else if (is.obj(shadows)) {
14709
15208
  Object.assign(renderer.shadowMap, shadows);
14710
15209
  }
14711
- if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type)
15210
+ if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
14712
15211
  renderer.shadowMap.needsUpdate = true;
15212
+ }
15213
+ }
15214
+ if (!configured) {
15215
+ renderer.outputColorSpace = SRGBColorSpace;
15216
+ renderer.toneMapping = ACESFilmicToneMapping;
14713
15217
  }
14714
15218
  if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
14715
15219
  if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
14716
15220
  lastConfiguredProps.textureColorSpace = textureColorSpace;
14717
15221
  }
14718
- if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose))
15222
+ if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
14719
15223
  applyProps(renderer, glConfig);
15224
+ }
14720
15225
  if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
14721
15226
  const currentRenderer = state.renderer;
14722
15227
  if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
@@ -14726,11 +15231,26 @@ function createRoot(canvas) {
14726
15231
  const scheduler = getScheduler();
14727
15232
  const rootId = state.internal.rootId;
14728
15233
  if (!rootId) {
14729
- const newRootId = scheduler.generateRootId();
15234
+ const newRootId = canvasId || scheduler.generateRootId();
14730
15235
  const unregisterRoot = scheduler.registerRoot(newRootId, {
14731
15236
  getState: () => store.getState(),
14732
15237
  onError: (err) => store.getState().setError(err)
14733
15238
  });
15239
+ const unregisterCanvasTarget = scheduler.register(
15240
+ () => {
15241
+ const state2 = store.getState();
15242
+ if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
15243
+ const renderer2 = state2.internal.actualRenderer;
15244
+ renderer2.setCanvasTarget(state2.internal.canvasTarget);
15245
+ }
15246
+ },
15247
+ {
15248
+ id: `${newRootId}_canvasTarget`,
15249
+ rootId: newRootId,
15250
+ phase: "start",
15251
+ system: true
15252
+ }
15253
+ );
14734
15254
  const unregisterFrustum = scheduler.register(
14735
15255
  () => {
14736
15256
  const state2 = store.getState();
@@ -14772,11 +15292,15 @@ function createRoot(canvas) {
14772
15292
  }
14773
15293
  },
14774
15294
  {
14775
- id: `${newRootId}_render`,
15295
+ // Use canvas ID directly as job ID if available, otherwise use generated rootId
15296
+ id: canvasId || `${newRootId}_render`,
14776
15297
  rootId: newRootId,
14777
15298
  phase: "render",
14778
- system: true
15299
+ system: true,
14779
15300
  // Internal flag: this is a system job, not user-controlled
15301
+ // Apply scheduler config for render ordering and rate limiting
15302
+ ...schedulerConfig?.after && { after: schedulerConfig.after },
15303
+ ...schedulerConfig?.fps && { fps: schedulerConfig.fps }
14780
15304
  }
14781
15305
  );
14782
15306
  state.set((state2) => ({
@@ -14785,6 +15309,7 @@ function createRoot(canvas) {
14785
15309
  rootId: newRootId,
14786
15310
  unregisterRoot: () => {
14787
15311
  unregisterRoot();
15312
+ unregisterCanvasTarget();
14788
15313
  unregisterFrustum();
14789
15314
  unregisterVisibility();
14790
15315
  unregisterRender();
@@ -14843,15 +15368,24 @@ function unmountComponentAtNode(canvas, callback) {
14843
15368
  const renderer = state.internal.actualRenderer;
14844
15369
  const unregisterRoot = state.internal.unregisterRoot;
14845
15370
  if (unregisterRoot) unregisterRoot();
15371
+ const unregisterPrimary = state.internal.unregisterPrimary;
15372
+ if (unregisterPrimary) unregisterPrimary();
15373
+ const canvasTarget = state.internal.canvasTarget;
15374
+ if (canvasTarget?.dispose) canvasTarget.dispose();
14846
15375
  state.events.disconnect?.();
14847
15376
  cleanupHelperGroup(root.store);
14848
- renderer?.renderLists?.dispose?.();
14849
- renderer?.forceContextLoss?.();
14850
- if (renderer?.xr) state.xr.disconnect();
15377
+ if (state.isLegacy && renderer) {
15378
+ ;
15379
+ renderer.renderLists?.dispose?.();
15380
+ renderer.forceContextLoss?.();
15381
+ }
15382
+ if (!state.internal.isSecondary) {
15383
+ if (renderer?.xr) state.xr.disconnect();
15384
+ }
14851
15385
  dispose(state.scene);
14852
15386
  _roots.delete(canvas);
14853
15387
  if (callback) callback(canvas);
14854
- } catch (e) {
15388
+ } catch {
14855
15389
  }
14856
15390
  }, 500);
14857
15391
  }
@@ -14859,36 +15393,34 @@ function unmountComponentAtNode(canvas, callback) {
14859
15393
  }
14860
15394
  }
14861
15395
  function createPortal(children, container, state) {
14862
- return /* @__PURE__ */ jsx(PortalWrapper, { children, container, state });
15396
+ return /* @__PURE__ */ jsx(Portal, { children, container, state });
14863
15397
  }
14864
- function PortalWrapper({ children, container, state }) {
15398
+ function Portal({ children, container, state }) {
14865
15399
  const isRef = useCallback((obj) => obj && "current" in obj, []);
14866
- const [resolvedContainer, setResolvedContainer] = useState(() => {
15400
+ const [resolvedContainer, _setResolvedContainer] = useState(() => {
14867
15401
  if (isRef(container)) return container.current ?? null;
14868
15402
  return container;
14869
15403
  });
15404
+ const setResolvedContainer = useCallback(
15405
+ (newContainer) => {
15406
+ if (!newContainer || newContainer === resolvedContainer) return;
15407
+ _setResolvedContainer(isRef(newContainer) ? newContainer.current : newContainer);
15408
+ },
15409
+ [resolvedContainer, _setResolvedContainer, isRef]
15410
+ );
14870
15411
  useMemo(() => {
14871
- if (isRef(container)) {
14872
- const current = container.current;
14873
- if (!current) {
14874
- queueMicrotask(() => {
14875
- const updated = container.current;
14876
- if (updated && updated !== resolvedContainer) {
14877
- setResolvedContainer(updated);
14878
- }
14879
- });
14880
- } else if (current !== resolvedContainer) {
14881
- setResolvedContainer(current);
14882
- }
14883
- } else if (container !== resolvedContainer) {
14884
- setResolvedContainer(container);
15412
+ if (isRef(container) && !container.current) {
15413
+ return queueMicrotask(() => {
15414
+ setResolvedContainer(container.current);
15415
+ });
14885
15416
  }
14886
- }, [container, resolvedContainer, isRef]);
15417
+ setResolvedContainer(container);
15418
+ }, [container, isRef, setResolvedContainer]);
14887
15419
  if (!resolvedContainer) return /* @__PURE__ */ jsx(Fragment, {});
14888
15420
  const portalKey = resolvedContainer.uuid ?? `portal-${resolvedContainer.id ?? "unknown"}`;
14889
- return /* @__PURE__ */ jsx(Portal, { children, container: resolvedContainer, state }, portalKey);
15421
+ return /* @__PURE__ */ jsx(PortalInner, { children, container: resolvedContainer, state }, portalKey);
14890
15422
  }
14891
- function Portal({ state = {}, children, container }) {
15423
+ function PortalInner({ state = {}, children, container }) {
14892
15424
  const { events, size, injectScene = true, ...rest } = state;
14893
15425
  const previousRoot = useStore();
14894
15426
  const [raycaster] = useState(() => new Raycaster());
@@ -14909,11 +15441,12 @@ function Portal({ state = {}, children, container }) {
14909
15441
  };
14910
15442
  }, [portalScene, container, injectScene]);
14911
15443
  const inject = useMutableCallback((rootState, injectState) => {
15444
+ const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
14912
15445
  let viewport = void 0;
14913
- if (injectState.camera && size) {
15446
+ if (injectState.camera && (size || injectState.size)) {
14914
15447
  const camera = injectState.camera;
14915
- viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), size);
14916
- if (camera !== rootState.camera) updateCamera(camera, size);
15448
+ viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), resolvedSize);
15449
+ if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
14917
15450
  }
14918
15451
  return {
14919
15452
  // The intersect consists of the previous root state
@@ -14930,7 +15463,7 @@ function Portal({ state = {}, children, container }) {
14930
15463
  previousRoot,
14931
15464
  // Events, size and viewport can be overridden by the inject layer
14932
15465
  events: { ...rootState.events, ...injectState.events, ...events },
14933
- size: { ...rootState.size, ...size },
15466
+ size: resolvedSize,
14934
15467
  viewport: { ...rootState.viewport, ...viewport },
14935
15468
  // Layers are allowed to override events
14936
15469
  setEvents: (events2) => injectState.set((state2) => ({ ...state2, events: { ...state2.events, ...events2 } })),
@@ -14964,15 +15497,13 @@ function CanvasImpl({
14964
15497
  fallback,
14965
15498
  resize,
14966
15499
  style,
15500
+ id,
14967
15501
  gl,
14968
- renderer,
15502
+ renderer: rendererProp,
14969
15503
  events = createPointerEvents,
14970
15504
  eventSource,
14971
15505
  eventPrefix,
14972
15506
  shadows,
14973
- linear,
14974
- flat,
14975
- legacy,
14976
15507
  orthographic,
14977
15508
  frameloop,
14978
15509
  dpr,
@@ -14984,10 +15515,46 @@ function CanvasImpl({
14984
15515
  onDragOverMissed,
14985
15516
  onDropMissed,
14986
15517
  onCreated,
15518
+ hmr,
15519
+ width,
15520
+ height,
15521
+ background,
15522
+ forceEven,
14987
15523
  ...props
14988
15524
  }) {
15525
+ const { primaryCanvas, scheduler, ...rendererConfig } = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp) ? rendererProp : { primaryCanvas: void 0, scheduler: void 0 };
15526
+ const renderer = Object.keys(rendererConfig).length > 0 ? rendererConfig : rendererProp;
14989
15527
  React.useMemo(() => extend(THREE), []);
14990
15528
  const Bridge = useBridge();
15529
+ const backgroundProps = React.useMemo(() => {
15530
+ if (!background) return null;
15531
+ if (typeof background === "object" && !background.isColor) {
15532
+ const { backgroundMap, envMap, files, preset, ...rest } = background;
15533
+ return {
15534
+ ...rest,
15535
+ preset,
15536
+ files: envMap || files,
15537
+ backgroundFiles: backgroundMap,
15538
+ background: true
15539
+ };
15540
+ }
15541
+ if (typeof background === "number") {
15542
+ return { color: background, background: true };
15543
+ }
15544
+ if (typeof background === "string") {
15545
+ if (background in presetsObj) {
15546
+ return { preset: background, background: true };
15547
+ }
15548
+ if (/^(https?:\/\/|\/|\.\/|\.\.\/)|\\.(hdr|exr|jpg|jpeg|png|webp|gif)$/i.test(background)) {
15549
+ return { files: background, background: true };
15550
+ }
15551
+ return { color: background, background: true };
15552
+ }
15553
+ if (background.isColor) {
15554
+ return { color: background, background: true };
15555
+ }
15556
+ return null;
15557
+ }, [background]);
14991
15558
  const hasInitialSizeRef = React.useRef(false);
14992
15559
  const measureConfig = React.useMemo(() => {
14993
15560
  if (!hasInitialSizeRef.current) {
@@ -15004,7 +15571,21 @@ function CanvasImpl({
15004
15571
  };
15005
15572
  }, [resize, hasInitialSizeRef.current]);
15006
15573
  const [containerRef, containerRect] = useMeasure(measureConfig);
15007
- if (!hasInitialSizeRef.current && containerRect.width > 0 && containerRect.height > 0) {
15574
+ const effectiveSize = React.useMemo(() => {
15575
+ let w = width ?? containerRect.width;
15576
+ let h = height ?? containerRect.height;
15577
+ if (forceEven) {
15578
+ w = Math.ceil(w / 2) * 2;
15579
+ h = Math.ceil(h / 2) * 2;
15580
+ }
15581
+ return {
15582
+ width: w,
15583
+ height: h,
15584
+ top: containerRect.top,
15585
+ left: containerRect.left
15586
+ };
15587
+ }, [width, height, containerRect, forceEven]);
15588
+ if (!hasInitialSizeRef.current && effectiveSize.width > 0 && effectiveSize.height > 0) {
15008
15589
  hasInitialSizeRef.current = true;
15009
15590
  }
15010
15591
  const canvasRef = React.useRef(null);
@@ -15023,7 +15604,7 @@ function CanvasImpl({
15023
15604
  useIsomorphicLayoutEffect(() => {
15024
15605
  effectActiveRef.current = true;
15025
15606
  const canvas = canvasRef.current;
15026
- if (containerRect.width > 0 && containerRect.height > 0 && canvas) {
15607
+ if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
15027
15608
  if (!root.current) {
15028
15609
  root.current = createRoot(canvas);
15029
15610
  notifyAlpha({
@@ -15043,21 +15624,24 @@ function CanvasImpl({
15043
15624
  async function run() {
15044
15625
  if (!effectActiveRef.current || !root.current) return;
15045
15626
  await root.current.configure({
15627
+ id,
15628
+ primaryCanvas,
15629
+ scheduler,
15046
15630
  gl,
15047
15631
  renderer,
15048
15632
  scene,
15049
15633
  events,
15050
15634
  shadows,
15051
- linear,
15052
- flat,
15053
- legacy,
15054
15635
  orthographic,
15055
15636
  frameloop,
15056
15637
  dpr,
15057
15638
  performance,
15058
15639
  raycaster,
15059
15640
  camera,
15060
- size: containerRect,
15641
+ size: effectiveSize,
15642
+ // Store size props for reset functionality
15643
+ _sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
15644
+ forceEven,
15061
15645
  // Pass mutable reference to onPointerMissed so it's free to update
15062
15646
  onPointerMissed: (...args) => handlePointerMissed.current?.(...args),
15063
15647
  onDragOverMissed: (...args) => handleDragOverMissed.current?.(...args),
@@ -15081,7 +15665,10 @@ function CanvasImpl({
15081
15665
  });
15082
15666
  if (!effectActiveRef.current || !root.current) return;
15083
15667
  root.current.render(
15084
- /* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsx(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: children ?? null }) }) })
15668
+ /* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: [
15669
+ backgroundProps && /* @__PURE__ */ jsx(Environment, { ...backgroundProps }),
15670
+ children ?? null
15671
+ ] }) }) })
15085
15672
  );
15086
15673
  }
15087
15674
  run();
@@ -15103,6 +15690,35 @@ function CanvasImpl({
15103
15690
  };
15104
15691
  }
15105
15692
  }, []);
15693
+ React.useEffect(() => {
15694
+ if (hmr === false) return;
15695
+ const canvas = canvasRef.current;
15696
+ if (!canvas) return;
15697
+ const handleHMR = () => {
15698
+ queueMicrotask(() => {
15699
+ const rootEntry = _roots.get(canvas);
15700
+ if (rootEntry?.store) {
15701
+ rootEntry.store.setState((state) => ({
15702
+ nodes: {},
15703
+ uniforms: {},
15704
+ _hmrVersion: state._hmrVersion + 1
15705
+ }));
15706
+ }
15707
+ });
15708
+ };
15709
+ if (typeof import.meta !== "undefined" && import.meta.hot) {
15710
+ const hot = import.meta.hot;
15711
+ hot.on("vite:afterUpdate", handleHMR);
15712
+ return () => hot.dispose?.(() => {
15713
+ });
15714
+ }
15715
+ if (typeof module !== "undefined" && module.hot) {
15716
+ const hot = module.hot;
15717
+ hot.addStatusHandler((status) => {
15718
+ if (status === "idle") handleHMR();
15719
+ });
15720
+ }
15721
+ }, [hmr]);
15106
15722
  const pointerEvents = eventSource ? "none" : "auto";
15107
15723
  return /* @__PURE__ */ jsx(
15108
15724
  "div",
@@ -15117,7 +15733,7 @@ function CanvasImpl({
15117
15733
  ...style
15118
15734
  },
15119
15735
  ...props,
15120
- children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef, className: "r3f-canvas", style: { display: "block" }, children: fallback }) })
15736
+ children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef, id, className: "r3f-canvas", style: { display: "block" }, children: fallback }) })
15121
15737
  }
15122
15738
  );
15123
15739
  }
@@ -15125,6 +15741,88 @@ function Canvas(props) {
15125
15741
  return /* @__PURE__ */ jsx(FiberProvider, { children: /* @__PURE__ */ jsx(CanvasImpl, { ...props }) });
15126
15742
  }
15127
15743
 
15744
+ var __defProp = Object.defineProperty;
15745
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
15746
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
15747
+ var _a;
15748
+ const INTERNAL_DATA = Symbol("ScopedStore.data");
15749
+ _a = INTERNAL_DATA;
15750
+ const _ScopedStore = class _ScopedStore {
15751
+ constructor(data) {
15752
+ __publicField(this, _a);
15753
+ this[INTERNAL_DATA] = data;
15754
+ return new Proxy(this, {
15755
+ get(target, prop, receiver) {
15756
+ if (typeof prop === "string") {
15757
+ if (prop === "scope" || prop === "has" || prop === "keys") {
15758
+ return Reflect.get(target, prop, receiver);
15759
+ }
15760
+ return target[INTERNAL_DATA][prop];
15761
+ }
15762
+ return Reflect.get(target, prop, receiver);
15763
+ },
15764
+ has(target, prop) {
15765
+ return typeof prop === "string" ? prop in target[INTERNAL_DATA] : Reflect.has(target, prop);
15766
+ },
15767
+ ownKeys(target) {
15768
+ return Reflect.ownKeys(target[INTERNAL_DATA]);
15769
+ },
15770
+ getOwnPropertyDescriptor(target, prop) {
15771
+ if (typeof prop === "string" && prop in target[INTERNAL_DATA]) {
15772
+ return {
15773
+ configurable: true,
15774
+ enumerable: true,
15775
+ value: target[INTERNAL_DATA][prop]
15776
+ };
15777
+ }
15778
+ return void 0;
15779
+ }
15780
+ });
15781
+ }
15782
+ /**
15783
+ * Access a nested scope by key.
15784
+ * If the key doesn't exist or isn't a scope object, returns an empty ScopedStore.
15785
+ */
15786
+ scope(key) {
15787
+ const data = this[INTERNAL_DATA][key];
15788
+ return new _ScopedStore(
15789
+ data && typeof data === "object" ? data : {}
15790
+ );
15791
+ }
15792
+ /**
15793
+ * Check if a key exists in the store.
15794
+ */
15795
+ has(key) {
15796
+ return key in this[INTERNAL_DATA];
15797
+ }
15798
+ /**
15799
+ * Get all keys in the store.
15800
+ */
15801
+ keys() {
15802
+ return Object.keys(this[INTERNAL_DATA]);
15803
+ }
15804
+ };
15805
+ let ScopedStore = _ScopedStore;
15806
+ function createScopedStore(data) {
15807
+ return new ScopedStore(data);
15808
+ }
15809
+ function createLazyCreatorState(state) {
15810
+ let _uniforms = null;
15811
+ let _nodes = null;
15812
+ return Object.create(state, {
15813
+ uniforms: {
15814
+ get() {
15815
+ return _uniforms ?? (_uniforms = createScopedStore(state.uniforms));
15816
+ }
15817
+ },
15818
+ nodes: {
15819
+ get() {
15820
+ return _nodes ?? (_nodes = createScopedStore(state.nodes));
15821
+ }
15822
+ }
15823
+ });
15824
+ }
15825
+
15128
15826
  function addTexture(set, key, value) {
15129
15827
  set((state) => {
15130
15828
  const newMap = new Map(state.textures);
@@ -15164,6 +15862,27 @@ function createTextureOperations(set) {
15164
15862
  removeMultiple: (keys) => removeTextures(set, keys)
15165
15863
  };
15166
15864
  }
15865
+ function extractTSLValue(value) {
15866
+ if (value === null || value === void 0) return value;
15867
+ if (typeof value !== "object") return value;
15868
+ const node = value;
15869
+ if (!node.isNode) return value;
15870
+ if (node.isConstNode) {
15871
+ return node.value;
15872
+ }
15873
+ if ("value" in node) {
15874
+ let extractedValue = node.value;
15875
+ if (typeof node.traverse === "function") {
15876
+ node.traverse((n) => {
15877
+ if (n.isConstNode) {
15878
+ extractedValue = n.value;
15879
+ }
15880
+ });
15881
+ }
15882
+ return extractedValue;
15883
+ }
15884
+ return value;
15885
+ }
15167
15886
  function vectorize(inObject) {
15168
15887
  if (inObject === null || inObject === void 0) return inObject;
15169
15888
  if (typeof inObject === "string") {
@@ -15176,6 +15895,9 @@ function vectorize(inObject) {
15176
15895
  }
15177
15896
  if (typeof inObject !== "object") return inObject;
15178
15897
  const obj = inObject;
15898
+ if (obj.isNode) {
15899
+ return extractTSLValue(inObject);
15900
+ }
15179
15901
  if (obj.isVector2 || obj.isVector3 || obj.isVector4) return inObject;
15180
15902
  if (obj.isMatrix3 || obj.isMatrix4) return inObject;
15181
15903
  if (obj.isColor || obj.isEuler || obj.isQuaternion || obj.isSpherical) return inObject;
@@ -15238,21 +15960,55 @@ function useUniforms(creatorOrScope, scope) {
15238
15960
  },
15239
15961
  [store]
15240
15962
  );
15963
+ const rebuildUniforms = useCallback(
15964
+ (targetScope) => {
15965
+ store.setState((state) => {
15966
+ let newUniforms = {};
15967
+ if (targetScope && targetScope !== "root") {
15968
+ const { [targetScope]: _, ...rest } = state.uniforms;
15969
+ newUniforms = rest;
15970
+ } else if (targetScope === "root") {
15971
+ for (const [key, value] of Object.entries(state.uniforms)) {
15972
+ if (!isUniformNode$1(value)) newUniforms[key] = value;
15973
+ }
15974
+ }
15975
+ return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
15976
+ });
15977
+ },
15978
+ [store]
15979
+ );
15241
15980
  const inputForMemoization = useMemo(() => {
15242
- return is.fun(creatorOrScope) ? creatorOrScope(store.getState()) : creatorOrScope;
15981
+ let raw = creatorOrScope;
15982
+ if (is.fun(creatorOrScope)) {
15983
+ const wrappedState = createLazyCreatorState(store.getState());
15984
+ raw = creatorOrScope(wrappedState);
15985
+ }
15986
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
15987
+ const normalized = {};
15988
+ for (const [key, value] of Object.entries(raw)) {
15989
+ normalized[key] = vectorize(value);
15990
+ }
15991
+ return normalized;
15992
+ }
15993
+ return raw;
15243
15994
  }, [creatorOrScope, store]);
15244
15995
  const memoizedInput = useCompareMemoize(inputForMemoization);
15996
+ const isReader = memoizedInput === void 0 || typeof memoizedInput === "string";
15997
+ const storeUniforms = useThree((s) => s.uniforms);
15998
+ const hmrVersion = useThree((s) => s._hmrVersion);
15999
+ const readerDep = isReader ? storeUniforms : null;
16000
+ const creatorDep = isReader ? null : hmrVersion;
15245
16001
  const uniforms = useMemo(() => {
15246
- const state = store.getState();
15247
- const set = store.setState;
15248
16002
  if (memoizedInput === void 0) {
15249
- return state.uniforms;
16003
+ return storeUniforms;
15250
16004
  }
15251
16005
  if (typeof memoizedInput === "string") {
15252
- const scopeData = state.uniforms[memoizedInput];
16006
+ const scopeData = storeUniforms[memoizedInput];
15253
16007
  if (scopeData && !isUniformNode$1(scopeData)) return scopeData;
15254
16008
  return {};
15255
16009
  }
16010
+ const state = store.getState();
16011
+ const set = store.setState;
15256
16012
  if (typeof memoizedInput !== "object" || memoizedInput === null) {
15257
16013
  throw new Error("Invalid uniform input");
15258
16014
  }
@@ -15296,8 +16052,22 @@ function useUniforms(creatorOrScope, scope) {
15296
16052
  }
15297
16053
  }
15298
16054
  return result;
15299
- }, [store, memoizedInput, scope]);
15300
- return { ...uniforms, removeUniforms: removeUniforms2, clearUniforms };
16055
+ }, [store, memoizedInput, scope, readerDep, creatorDep]);
16056
+ return { ...uniforms, removeUniforms: removeUniforms2, clearUniforms, rebuildUniforms };
16057
+ }
16058
+ function rebuildAllUniforms(store, scope) {
16059
+ store.setState((state) => {
16060
+ let newUniforms = {};
16061
+ if (scope && scope !== "root") {
16062
+ const { [scope]: _, ...rest } = state.uniforms;
16063
+ newUniforms = rest;
16064
+ } else if (scope === "root") {
16065
+ for (const [key, value] of Object.entries(state.uniforms)) {
16066
+ if (!isUniformNode$1(value)) newUniforms[key] = value;
16067
+ }
16068
+ }
16069
+ return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
16070
+ });
15301
16071
  }
15302
16072
  function removeUniforms(set, names, scope) {
15303
16073
  set((state) => {
@@ -15362,15 +16132,17 @@ function isSameThreeType(a, b) {
15362
16132
  }
15363
16133
 
15364
16134
  const isUniformNode = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
16135
+ const isTSLNode$1 = (value) => value !== null && typeof value === "object" && "uuid" in value && "nodeType" in value;
15365
16136
  function useUniform(name, value) {
15366
16137
  const store = useStore();
16138
+ const hmrVersion = useThree((s) => s._hmrVersion);
15367
16139
  return useMemo(() => {
15368
16140
  const state = store.getState();
15369
16141
  const set = store.setState;
15370
16142
  const existing = state.uniforms[name];
15371
16143
  if (existing && isUniformNode(existing)) {
15372
- if (value !== void 0) {
15373
- existing.value = value;
16144
+ if (value !== void 0 && !isTSLNode$1(value) && !isUniformNode(value)) {
16145
+ existing.value = typeof value === "string" ? new Color(value) : value;
15374
16146
  }
15375
16147
  return existing;
15376
16148
  }
@@ -15379,7 +16151,24 @@ function useUniform(name, value) {
15379
16151
  `[useUniform] Uniform "${name}" not found. Create it first with: useUniform('${name}', initialValue)`
15380
16152
  );
15381
16153
  }
15382
- const node = uniform(value);
16154
+ if (isUniformNode(value)) {
16155
+ const node2 = value;
16156
+ if (typeof node2.setName === "function") {
16157
+ node2.setName(name);
16158
+ }
16159
+ set((s) => ({
16160
+ uniforms: { ...s.uniforms, [name]: node2 }
16161
+ }));
16162
+ return node2;
16163
+ }
16164
+ let node;
16165
+ if (isTSLNode$1(value)) {
16166
+ node = uniform(value);
16167
+ } else if (typeof value === "string") {
16168
+ node = uniform(new Color(value));
16169
+ } else {
16170
+ node = uniform(value);
16171
+ }
15383
16172
  if (typeof node.setName === "function") {
15384
16173
  node.setName(name);
15385
16174
  }
@@ -15390,7 +16179,7 @@ function useUniform(name, value) {
15390
16179
  }
15391
16180
  }));
15392
16181
  return node;
15393
- }, [store, name]);
16182
+ }, [store, name, hmrVersion]);
15394
16183
  }
15395
16184
 
15396
16185
  const isTSLNode = (value) => value !== null && typeof value === "object" && ("uuid" in value || "nodeType" in value);
@@ -15431,19 +16220,46 @@ function useNodes(creatorOrScope, scope) {
15431
16220
  },
15432
16221
  [store]
15433
16222
  );
16223
+ const rebuildNodes = useCallback(
16224
+ (targetScope) => {
16225
+ store.setState((state) => {
16226
+ let newNodes = state.nodes;
16227
+ if (targetScope && targetScope !== "root") {
16228
+ const { [targetScope]: _, ...rest } = state.nodes;
16229
+ newNodes = rest;
16230
+ } else if (targetScope === "root") {
16231
+ newNodes = {};
16232
+ for (const [key, value] of Object.entries(state.nodes)) {
16233
+ if (!isTSLNode(value)) newNodes[key] = value;
16234
+ }
16235
+ } else {
16236
+ newNodes = {};
16237
+ }
16238
+ return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
16239
+ });
16240
+ },
16241
+ [store]
16242
+ );
16243
+ const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
16244
+ const storeNodes = useThree((s) => s.nodes);
16245
+ const hmrVersion = useThree((s) => s._hmrVersion);
16246
+ const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
16247
+ const readerDep = isReader ? storeNodes : null;
16248
+ const creatorDep = isReader ? null : hmrVersion;
15434
16249
  const nodes = useMemo(() => {
15435
- const state = store.getState();
15436
- const set = store.setState;
15437
16250
  if (creatorOrScope === void 0) {
15438
- return state.nodes;
16251
+ return storeNodes;
15439
16252
  }
15440
16253
  if (typeof creatorOrScope === "string") {
15441
- const scopeData = state.nodes[creatorOrScope];
16254
+ const scopeData = storeNodes[creatorOrScope];
15442
16255
  if (scopeData && !isTSLNode(scopeData)) return scopeData;
15443
16256
  return {};
15444
16257
  }
16258
+ const state = store.getState();
16259
+ const set = store.setState;
15445
16260
  const creator = creatorOrScope;
15446
- const created = creator(state);
16261
+ const wrappedState = createLazyCreatorState(state);
16262
+ const created = creator(wrappedState);
15447
16263
  const result = {};
15448
16264
  let hasNewNodes = false;
15449
16265
  if (scope) {
@@ -15452,7 +16268,7 @@ function useNodes(creatorOrScope, scope) {
15452
16268
  if (currentScope[name]) {
15453
16269
  result[name] = currentScope[name];
15454
16270
  } else {
15455
- if (typeof node.label === "function") node.setName(`${scope}.${name}`);
16271
+ node.setName?.(`${scope}.${name}`);
15456
16272
  result[name] = node;
15457
16273
  hasNewNodes = true;
15458
16274
  }
@@ -15472,7 +16288,7 @@ function useNodes(creatorOrScope, scope) {
15472
16288
  if (existing && isTSLNode(existing)) {
15473
16289
  result[name] = existing;
15474
16290
  } else {
15475
- if (typeof node.label === "function") node.setName(name);
16291
+ node.setName?.(name);
15476
16292
  result[name] = node;
15477
16293
  hasNewNodes = true;
15478
16294
  }
@@ -15481,8 +16297,25 @@ function useNodes(creatorOrScope, scope) {
15481
16297
  set((s) => ({ nodes: { ...s.nodes, ...result } }));
15482
16298
  }
15483
16299
  return result;
15484
- }, [store, typeof creatorOrScope === "string" ? creatorOrScope : scope]);
15485
- return { ...nodes, removeNodes: removeNodes2, clearNodes };
16300
+ }, [store, scopeDep, readerDep, creatorDep]);
16301
+ return { ...nodes, removeNodes: removeNodes2, clearNodes, rebuildNodes };
16302
+ }
16303
+ function rebuildAllNodes(store, scope) {
16304
+ store.setState((state) => {
16305
+ let newNodes = state.nodes;
16306
+ if (scope && scope !== "root") {
16307
+ const { [scope]: _, ...rest } = state.nodes;
16308
+ newNodes = rest;
16309
+ } else if (scope === "root") {
16310
+ newNodes = {};
16311
+ for (const [key, value] of Object.entries(state.nodes)) {
16312
+ if (!isTSLNode(value)) newNodes[key] = value;
16313
+ }
16314
+ } else {
16315
+ newNodes = {};
16316
+ }
16317
+ return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
16318
+ });
15486
16319
  }
15487
16320
  function removeNodes(set, names, scope) {
15488
16321
  set((state) => {
@@ -15516,10 +16349,11 @@ function useLocalNodes(creator) {
15516
16349
  const uniforms = useThree((s) => s.uniforms);
15517
16350
  const nodes = useThree((s) => s.nodes);
15518
16351
  const textures = useThree((s) => s.textures);
16352
+ const hmrVersion = useThree((s) => s._hmrVersion);
15519
16353
  return useMemo(() => {
15520
- const state = store.getState();
15521
- return creator(state);
15522
- }, [store, creator, uniforms, nodes, textures]);
16354
+ const wrappedState = createLazyCreatorState(store.getState());
16355
+ return creator(wrappedState);
16356
+ }, [store, creator, uniforms, nodes, textures, hmrVersion]);
15523
16357
  }
15524
16358
 
15525
16359
  function usePostProcessing(mainCB, setupCB) {
@@ -15532,6 +16366,10 @@ function usePostProcessing(mainCB, setupCB) {
15532
16366
  mainCBRef.current = mainCB;
15533
16367
  setupCBRef.current = setupCB;
15534
16368
  const [rebuildVersion, setRebuildVersion] = useState(0);
16369
+ useEffect(() => {
16370
+ callbacksRanRef.current = false;
16371
+ scenePassCacheRef.current = null;
16372
+ }, []);
15535
16373
  const clearPasses = useCallback(() => {
15536
16374
  store.setState({ passes: {} });
15537
16375
  }, [store]);
@@ -15613,4 +16451,4 @@ function usePostProcessing(mainCB, setupCB) {
15613
16451
 
15614
16452
  extend(THREE);
15615
16453
 
15616
- export { Block, Canvas, ErrorBoundary, IsObject, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Scheduler, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, clearNodeScope, clearRootNodes, clearRootUniforms, clearScope, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, createTextureOperations, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, getInstanceProps, getRootState, getScheduler, getUuidPrefix, hasConstructor, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isObject3D, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, prepare, reconciler, removeInteractivity, removeNodes, removeUniforms, resolve, unmountComponentAtNode, updateCamera, updateFrustum, useBridge, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, usePostProcessing, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms };
16454
+ export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Scheduler, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, clearNodeScope, clearRootNodes, clearRootUniforms, clearScope, context, createEvents, createPointerEvents, createPortal, createRoot, createScopedStore, createStore, createTextureOperations, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getScheduler, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, rebuildAllNodes, rebuildAllUniforms, reconciler, registerPrimary, removeInteractivity, removeNodes, removeUniforms, resolve, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, usePostProcessing, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms, waitForPrimary };