@react-three/fiber 10.0.0-alpha.0 → 10.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +613 -146
- package/dist/index.d.cts +230 -43
- package/dist/index.d.mts +230 -43
- package/dist/index.d.ts +230 -43
- package/dist/index.mjs +613 -149
- package/dist/legacy.cjs +607 -144
- package/dist/legacy.d.cts +231 -42
- package/dist/legacy.d.mts +231 -42
- package/dist/legacy.d.ts +231 -42
- package/dist/legacy.mjs +606 -146
- package/dist/webgpu/index.cjs +925 -251
- package/dist/webgpu/index.d.cts +361 -60
- package/dist/webgpu/index.d.mts +361 -60
- package/dist/webgpu/index.d.ts +361 -60
- package/dist/webgpu/index.mjs +921 -253
- package/package.json +5 -5
- package/react-reconciler/constants.js +1 -9
- package/react-reconciler/index.js +4 -20
package/dist/webgpu/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as webgpu from 'three/webgpu';
|
|
2
|
-
import { 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, 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';
|
|
3
3
|
import { Inspector } from 'three/addons/inspector/Inspector.js';
|
|
4
4
|
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import * as React from 'react';
|
|
@@ -34,18 +34,21 @@ const WebGLRenderer = class WebGLRenderer2 {
|
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
+
const WebGLRenderTarget = null;
|
|
37
38
|
|
|
38
39
|
const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
39
40
|
__proto__: null,
|
|
40
41
|
Inspector: Inspector,
|
|
41
42
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
42
43
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
44
|
+
RenderTargetCompat: RenderTarget,
|
|
45
|
+
WebGLRenderTarget: WebGLRenderTarget,
|
|
43
46
|
WebGLRenderer: WebGLRenderer
|
|
44
47
|
}, [webgpu]);
|
|
45
48
|
|
|
46
|
-
var __defProp$
|
|
47
|
-
var __defNormalProp$
|
|
48
|
-
var __publicField$
|
|
49
|
+
var __defProp$3 = Object.defineProperty;
|
|
50
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
51
|
+
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
49
52
|
const act = React["act"];
|
|
50
53
|
const useIsomorphicLayoutEffect = /* @__PURE__ */ (() => typeof window !== "undefined" && (window.document?.createElement || window.navigator?.product === "ReactNative"))() ? React.useLayoutEffect : React.useEffect;
|
|
51
54
|
function useMutableCallback(fn) {
|
|
@@ -77,7 +80,7 @@ const ErrorBoundary = /* @__PURE__ */ (() => {
|
|
|
77
80
|
return _a = class extends React.Component {
|
|
78
81
|
constructor() {
|
|
79
82
|
super(...arguments);
|
|
80
|
-
__publicField$
|
|
83
|
+
__publicField$3(this, "state", { error: false });
|
|
81
84
|
}
|
|
82
85
|
componentDidCatch(err) {
|
|
83
86
|
this.props.set(err);
|
|
@@ -85,7 +88,7 @@ const ErrorBoundary = /* @__PURE__ */ (() => {
|
|
|
85
88
|
render() {
|
|
86
89
|
return this.state.error ? null : this.props.children;
|
|
87
90
|
}
|
|
88
|
-
}, __publicField$
|
|
91
|
+
}, __publicField$3(_a, "getDerivedStateFromError", () => ({ error: true })), _a;
|
|
89
92
|
})();
|
|
90
93
|
|
|
91
94
|
const is = {
|
|
@@ -148,6 +151,13 @@ function updateCamera(camera, size) {
|
|
|
148
151
|
}
|
|
149
152
|
camera.updateProjectionMatrix();
|
|
150
153
|
}
|
|
154
|
+
const frustumMatrix = new Matrix4();
|
|
155
|
+
function updateFrustum(camera, frustum) {
|
|
156
|
+
const target = frustum ?? new Frustum();
|
|
157
|
+
frustumMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
158
|
+
target.setFromProjectionMatrix(frustumMatrix);
|
|
159
|
+
return target;
|
|
160
|
+
}
|
|
151
161
|
|
|
152
162
|
const REACT_INTERNAL_PROPS = ["children", "key", "ref"];
|
|
153
163
|
function findInitialRoot(instance) {
|
|
@@ -228,6 +238,205 @@ function invalidateInstance(instance) {
|
|
|
228
238
|
if (state && state.internal.frames === 0) state.invalidate();
|
|
229
239
|
}
|
|
230
240
|
|
|
241
|
+
const tempFrustum = new Frustum();
|
|
242
|
+
let hasWarnedWebGL = false;
|
|
243
|
+
let tslModule = null;
|
|
244
|
+
async function loadTSL() {
|
|
245
|
+
if (tslModule) return tslModule;
|
|
246
|
+
try {
|
|
247
|
+
const tsl = await import('three/tsl');
|
|
248
|
+
tslModule = { uniform: tsl.uniform, nodeObject: tsl.nodeObject };
|
|
249
|
+
return tslModule;
|
|
250
|
+
} catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function createOcclusionObserverNode(store, uniform) {
|
|
255
|
+
const node = new Node("float");
|
|
256
|
+
node.updateType = NodeUpdateType.OBJECT;
|
|
257
|
+
node.update = function(frame) {
|
|
258
|
+
const { internal } = store.getState();
|
|
259
|
+
const registry = internal.visibilityRegistry;
|
|
260
|
+
const cache = internal.occlusionCache;
|
|
261
|
+
for (const entry of registry.values()) {
|
|
262
|
+
const { object, handlers } = entry;
|
|
263
|
+
if (handlers.onOccluded || handlers.onVisible) {
|
|
264
|
+
const isOccluded = frame.renderer.isOccluded(object);
|
|
265
|
+
cache.set(object, isOccluded);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
node.setup = function() {
|
|
270
|
+
return uniform(0);
|
|
271
|
+
};
|
|
272
|
+
return node;
|
|
273
|
+
}
|
|
274
|
+
let occlusionSetupPromise = null;
|
|
275
|
+
function enableOcclusion(store) {
|
|
276
|
+
const state = store.getState();
|
|
277
|
+
const { internal, renderer, rootScene } = state;
|
|
278
|
+
if (internal.occlusionEnabled || occlusionSetupPromise) return;
|
|
279
|
+
const hasOcclusionSupport = typeof renderer?.isOccluded === "function";
|
|
280
|
+
if (!hasOcclusionSupport) {
|
|
281
|
+
if (!hasWarnedWebGL) {
|
|
282
|
+
console.warn(
|
|
283
|
+
"[R3F] Warning: onOccluded/onVisible occlusion queries require WebGPU renderer. Occlusion events will not fire on WebGL."
|
|
284
|
+
);
|
|
285
|
+
hasWarnedWebGL = true;
|
|
286
|
+
}
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
occlusionSetupPromise = setupOcclusion(store);
|
|
290
|
+
}
|
|
291
|
+
async function setupOcclusion(store) {
|
|
292
|
+
const state = store.getState();
|
|
293
|
+
const { internal, rootScene, set } = state;
|
|
294
|
+
const tsl = await loadTSL();
|
|
295
|
+
if (!tsl) {
|
|
296
|
+
console.warn("[R3F] Warning: TSL module not available. Occlusion queries disabled.");
|
|
297
|
+
occlusionSetupPromise = null;
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const { uniform, nodeObject } = tsl;
|
|
301
|
+
let helperGroup = internal.helperGroup;
|
|
302
|
+
if (!helperGroup) {
|
|
303
|
+
helperGroup = new Group();
|
|
304
|
+
helperGroup.name = "__r3fInternal";
|
|
305
|
+
helperGroup.__r3fInternal = true;
|
|
306
|
+
rootScene.add(helperGroup);
|
|
307
|
+
}
|
|
308
|
+
const geometry = new BoxGeometry(1, 1, 1);
|
|
309
|
+
const material = new MeshBasicNodeMaterial({
|
|
310
|
+
transparent: true,
|
|
311
|
+
opacity: 0
|
|
312
|
+
});
|
|
313
|
+
const observerNode = nodeObject(createOcclusionObserverNode(store, uniform));
|
|
314
|
+
material.colorNode = observerNode;
|
|
315
|
+
material.needsUpdate = true;
|
|
316
|
+
const mesh = new Mesh(geometry, material);
|
|
317
|
+
mesh.name = "__r3fOcclusionObserver";
|
|
318
|
+
mesh.scale.setScalar(1e-4);
|
|
319
|
+
mesh.frustumCulled = false;
|
|
320
|
+
mesh.__r3fInternal = true;
|
|
321
|
+
helperGroup.add(mesh);
|
|
322
|
+
set((state2) => ({
|
|
323
|
+
internal: {
|
|
324
|
+
...state2.internal,
|
|
325
|
+
helperGroup,
|
|
326
|
+
occlusionObserver: mesh,
|
|
327
|
+
occlusionEnabled: true
|
|
328
|
+
}
|
|
329
|
+
}));
|
|
330
|
+
occlusionSetupPromise = null;
|
|
331
|
+
}
|
|
332
|
+
function disableOcclusion(store) {
|
|
333
|
+
const { internal, set } = store.getState();
|
|
334
|
+
if (!internal.occlusionEnabled) return;
|
|
335
|
+
if (internal.occlusionObserver) {
|
|
336
|
+
internal.occlusionObserver.removeFromParent();
|
|
337
|
+
internal.occlusionObserver.geometry.dispose();
|
|
338
|
+
internal.occlusionObserver.material.dispose();
|
|
339
|
+
}
|
|
340
|
+
internal.occlusionCache.clear();
|
|
341
|
+
set((state) => ({
|
|
342
|
+
internal: {
|
|
343
|
+
...state.internal,
|
|
344
|
+
occlusionObserver: null,
|
|
345
|
+
occlusionEnabled: false
|
|
346
|
+
}
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
349
|
+
function cleanupHelperGroup(store) {
|
|
350
|
+
const { internal, set } = store.getState();
|
|
351
|
+
disableOcclusion(store);
|
|
352
|
+
if (internal.helperGroup) {
|
|
353
|
+
internal.helperGroup.removeFromParent();
|
|
354
|
+
set((state) => ({
|
|
355
|
+
internal: {
|
|
356
|
+
...state.internal,
|
|
357
|
+
helperGroup: null
|
|
358
|
+
}
|
|
359
|
+
}));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function registerVisibility(store, object, handlers) {
|
|
363
|
+
const { internal } = store.getState();
|
|
364
|
+
const registry = internal.visibilityRegistry;
|
|
365
|
+
const entry = {
|
|
366
|
+
object,
|
|
367
|
+
handlers,
|
|
368
|
+
lastFramedState: null,
|
|
369
|
+
lastOccludedState: null,
|
|
370
|
+
lastVisibleState: null
|
|
371
|
+
};
|
|
372
|
+
registry.set(object.uuid, entry);
|
|
373
|
+
if (handlers.onOccluded || handlers.onVisible) {
|
|
374
|
+
object.occlusionTest = true;
|
|
375
|
+
if (!internal.occlusionEnabled) {
|
|
376
|
+
enableOcclusion(store);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
function unregisterVisibility(store, object) {
|
|
381
|
+
const { internal } = store.getState();
|
|
382
|
+
internal.visibilityRegistry.delete(object.uuid);
|
|
383
|
+
internal.occlusionCache.delete(object);
|
|
384
|
+
}
|
|
385
|
+
function checkVisibility(state) {
|
|
386
|
+
const { internal, camera } = state;
|
|
387
|
+
const registry = internal.visibilityRegistry;
|
|
388
|
+
if (registry.size === 0) return;
|
|
389
|
+
updateFrustum(camera, tempFrustum);
|
|
390
|
+
for (const entry of registry.values()) {
|
|
391
|
+
const { object, handlers, lastFramedState, lastOccludedState, lastVisibleState } = entry;
|
|
392
|
+
let inFrustum = null;
|
|
393
|
+
const computeFrustum = () => {
|
|
394
|
+
if (inFrustum === null) {
|
|
395
|
+
if (object.geometry?.boundingSphere === null) {
|
|
396
|
+
object.geometry?.computeBoundingSphere();
|
|
397
|
+
}
|
|
398
|
+
inFrustum = tempFrustum.intersectsObject(object);
|
|
399
|
+
}
|
|
400
|
+
return inFrustum;
|
|
401
|
+
};
|
|
402
|
+
if (handlers.onFramed) {
|
|
403
|
+
const currentInFrustum = computeFrustum();
|
|
404
|
+
if (currentInFrustum !== lastFramedState) {
|
|
405
|
+
entry.lastFramedState = currentInFrustum;
|
|
406
|
+
handlers.onFramed(currentInFrustum);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
let currentOcclusion = null;
|
|
410
|
+
if (handlers.onOccluded && internal.occlusionEnabled) {
|
|
411
|
+
currentOcclusion = internal.occlusionCache.get(object) ?? null;
|
|
412
|
+
if (currentOcclusion !== null && currentOcclusion !== lastOccludedState) {
|
|
413
|
+
entry.lastOccludedState = currentOcclusion;
|
|
414
|
+
handlers.onOccluded(currentOcclusion);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (handlers.onVisible) {
|
|
418
|
+
const currentInFrustum = computeFrustum();
|
|
419
|
+
if (!handlers.onFramed && currentInFrustum !== lastFramedState) {
|
|
420
|
+
entry.lastFramedState = currentInFrustum;
|
|
421
|
+
}
|
|
422
|
+
let isOccluded = currentOcclusion;
|
|
423
|
+
if (isOccluded === null && internal.occlusionEnabled) {
|
|
424
|
+
isOccluded = internal.occlusionCache.get(object) ?? null;
|
|
425
|
+
}
|
|
426
|
+
if (isOccluded === null) isOccluded = false;
|
|
427
|
+
const isVisible = currentInFrustum && !isOccluded && object.visible;
|
|
428
|
+
if (isVisible !== lastVisibleState) {
|
|
429
|
+
entry.lastVisibleState = isVisible;
|
|
430
|
+
handlers.onVisible(isVisible);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
function hasVisibilityHandlers(handlers) {
|
|
436
|
+
if (!handlers) return false;
|
|
437
|
+
return !!(handlers.onFramed || handlers.onOccluded || handlers.onVisible);
|
|
438
|
+
}
|
|
439
|
+
|
|
231
440
|
const RESERVED_PROPS = [
|
|
232
441
|
"children",
|
|
233
442
|
"key",
|
|
@@ -242,6 +451,7 @@ const RESERVED_PROPS = [
|
|
|
242
451
|
"dispose"
|
|
243
452
|
];
|
|
244
453
|
const EVENT_REGEX = /^on(Pointer|Drag|Drop|Click|DoubleClick|ContextMenu|Wheel)/;
|
|
454
|
+
const VISIBILITY_EVENT_REGEX = /^on(Framed|Occluded|Visible)$/;
|
|
245
455
|
const INDEX_REGEX = /-\d+$/;
|
|
246
456
|
const MEMOIZED_PROTOTYPES = /* @__PURE__ */ new Map();
|
|
247
457
|
const colorMaps = ["map", "emissiveMap", "sheenColorMap", "specularColorMap", "envMap"];
|
|
@@ -328,7 +538,7 @@ function applyProps(object, props) {
|
|
|
328
538
|
const rootState = instance && findInitialRoot(instance).getState();
|
|
329
539
|
const prevHandlers = instance?.eventCount;
|
|
330
540
|
for (const prop in props) {
|
|
331
|
-
|
|
541
|
+
const value = props[prop];
|
|
332
542
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
333
543
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
334
544
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
@@ -336,6 +546,12 @@ function applyProps(object, props) {
|
|
|
336
546
|
instance.eventCount = Object.keys(instance.handlers).length;
|
|
337
547
|
continue;
|
|
338
548
|
}
|
|
549
|
+
if (instance && VISIBILITY_EVENT_REGEX.test(prop)) {
|
|
550
|
+
if (typeof value === "function") instance.handlers[prop] = value;
|
|
551
|
+
else delete instance.handlers[prop];
|
|
552
|
+
instance.eventCount = Object.keys(instance.handlers).length;
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
339
555
|
if (value === void 0) continue;
|
|
340
556
|
let { root, key, target } = resolve(object, prop);
|
|
341
557
|
if (target === void 0 && (typeof root !== "object" || root === null)) {
|
|
@@ -372,6 +588,17 @@ function applyProps(object, props) {
|
|
|
372
588
|
if (instance.eventCount && object2.raycast !== null) {
|
|
373
589
|
rootState.internal.interaction.push(object2);
|
|
374
590
|
}
|
|
591
|
+
const root = findInitialRoot(instance);
|
|
592
|
+
const visibilityHandlers = {
|
|
593
|
+
onFramed: instance.handlers.onFramed,
|
|
594
|
+
onOccluded: instance.handlers.onOccluded,
|
|
595
|
+
onVisible: instance.handlers.onVisible
|
|
596
|
+
};
|
|
597
|
+
if (hasVisibilityHandlers(visibilityHandlers)) {
|
|
598
|
+
registerVisibility(root, object2, visibilityHandlers);
|
|
599
|
+
} else {
|
|
600
|
+
unregisterVisibility(root, object2);
|
|
601
|
+
}
|
|
375
602
|
}
|
|
376
603
|
if (instance && instance.props.attach === void 0) {
|
|
377
604
|
if (instance.object.isBufferGeometry) instance.props.attach = "geometry";
|
|
@@ -406,6 +633,7 @@ function removeInteractivity(store, object) {
|
|
|
406
633
|
internal.capturedMap.forEach((captures, pointerId) => {
|
|
407
634
|
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
408
635
|
});
|
|
636
|
+
unregisterVisibility(store, object);
|
|
409
637
|
}
|
|
410
638
|
function createEvents(store) {
|
|
411
639
|
function calculateDistance(event) {
|
|
@@ -462,13 +690,14 @@ function createEvents(store) {
|
|
|
462
690
|
for (const hit of hits) {
|
|
463
691
|
let eventObject = hit.object;
|
|
464
692
|
while (eventObject) {
|
|
465
|
-
if (eventObject.__r3f?.eventCount)
|
|
693
|
+
if (eventObject.__r3f?.eventCount) {
|
|
466
694
|
intersections.push({ ...hit, eventObject });
|
|
695
|
+
}
|
|
467
696
|
eventObject = eventObject.parent;
|
|
468
697
|
}
|
|
469
698
|
}
|
|
470
699
|
if ("pointerId" in event && state.internal.capturedMap.has(event.pointerId)) {
|
|
471
|
-
for (
|
|
700
|
+
for (const captureData of state.internal.capturedMap.get(event.pointerId).values()) {
|
|
472
701
|
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
473
702
|
}
|
|
474
703
|
}
|
|
@@ -498,12 +727,12 @@ function createEvents(store) {
|
|
|
498
727
|
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
499
728
|
}
|
|
500
729
|
};
|
|
501
|
-
|
|
502
|
-
for (
|
|
503
|
-
|
|
730
|
+
const extractEventProps = {};
|
|
731
|
+
for (const prop in event) {
|
|
732
|
+
const property = event[prop];
|
|
504
733
|
if (typeof property !== "function") extractEventProps[prop] = property;
|
|
505
734
|
}
|
|
506
|
-
|
|
735
|
+
const raycastEvent = {
|
|
507
736
|
...hit,
|
|
508
737
|
...extractEventProps,
|
|
509
738
|
pointer,
|
|
@@ -788,8 +1017,21 @@ function formatLocation(url, line) {
|
|
|
788
1017
|
const file = clean.split("/").pop() ?? clean;
|
|
789
1018
|
return `${file}:${line}`;
|
|
790
1019
|
}
|
|
1020
|
+
function notifyAlpha({ message, link }) {
|
|
1021
|
+
if (typeof process !== "undefined" && (process.env.NODE_ENV === "test" || process.env.JEST_WORKER_ID !== void 0) && process.env.R3F_SHOW_ALPHA_WARNINGS !== "true") {
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
if (shownNotices.has(message)) return;
|
|
1025
|
+
shownNotices.add(message);
|
|
1026
|
+
const boxStyle = "background: #6366f1; color: #ffffff; padding: 6px 10px; border-radius: 4px; font-weight: 500;";
|
|
1027
|
+
console.log(`%c\u{1F52C} ${message}`, boxStyle);
|
|
1028
|
+
{
|
|
1029
|
+
console.log(`%cMore info: ${link}`, "color: #6366f1; font-weight: normal;");
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
791
1032
|
|
|
792
|
-
const
|
|
1033
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
1034
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
793
1035
|
const createStore = (invalidate, advance) => {
|
|
794
1036
|
const rootStore = createWithEqualityFn((set, get) => {
|
|
795
1037
|
const position = new Vector3();
|
|
@@ -820,6 +1062,8 @@ const createStore = (invalidate, advance) => {
|
|
|
820
1062
|
gl: null,
|
|
821
1063
|
renderer: null,
|
|
822
1064
|
camera: null,
|
|
1065
|
+
frustum: new Frustum(),
|
|
1066
|
+
autoUpdateFrustum: true,
|
|
823
1067
|
raycaster: null,
|
|
824
1068
|
events: { priority: 1, enabled: true, connected: false },
|
|
825
1069
|
scene: null,
|
|
@@ -871,10 +1115,38 @@ const createStore = (invalidate, advance) => {
|
|
|
871
1115
|
getCurrentViewport
|
|
872
1116
|
},
|
|
873
1117
|
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
874
|
-
setSize: (width, height, top
|
|
875
|
-
const
|
|
876
|
-
|
|
877
|
-
|
|
1118
|
+
setSize: (width, height, top, left) => {
|
|
1119
|
+
const state2 = get();
|
|
1120
|
+
if (width === void 0) {
|
|
1121
|
+
set({ _sizeImperative: false });
|
|
1122
|
+
if (state2._sizeProps) {
|
|
1123
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
1124
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
1125
|
+
const currentSize = state2.size;
|
|
1126
|
+
const newSize = {
|
|
1127
|
+
width: propW ?? currentSize.width,
|
|
1128
|
+
height: propH ?? currentSize.height,
|
|
1129
|
+
top: currentSize.top,
|
|
1130
|
+
left: currentSize.left
|
|
1131
|
+
};
|
|
1132
|
+
set((s) => ({
|
|
1133
|
+
size: newSize,
|
|
1134
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
1135
|
+
}));
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
const w = width;
|
|
1141
|
+
const h = height ?? width;
|
|
1142
|
+
const t = top ?? state2.size.top;
|
|
1143
|
+
const l = left ?? state2.size.left;
|
|
1144
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
1145
|
+
set((s) => ({
|
|
1146
|
+
size,
|
|
1147
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
1148
|
+
_sizeImperative: true
|
|
1149
|
+
}));
|
|
878
1150
|
},
|
|
879
1151
|
setDpr: (dpr) => set((state2) => {
|
|
880
1152
|
const resolved = calculateDpr(dpr);
|
|
@@ -891,6 +1163,9 @@ const createStore = (invalidate, advance) => {
|
|
|
891
1163
|
textures: /* @__PURE__ */ new Map(),
|
|
892
1164
|
postProcessing: null,
|
|
893
1165
|
passes: {},
|
|
1166
|
+
_hmrVersion: 0,
|
|
1167
|
+
_sizeImperative: false,
|
|
1168
|
+
_sizeProps: null,
|
|
894
1169
|
previousRoot: void 0,
|
|
895
1170
|
internal: {
|
|
896
1171
|
// Events
|
|
@@ -901,6 +1176,13 @@ const createStore = (invalidate, advance) => {
|
|
|
901
1176
|
initialHits: [],
|
|
902
1177
|
capturedMap: /* @__PURE__ */ new Map(),
|
|
903
1178
|
lastEvent: React.createRef(),
|
|
1179
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
1180
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
1181
|
+
// Occlusion system (WebGPU only)
|
|
1182
|
+
occlusionEnabled: false,
|
|
1183
|
+
occlusionObserver: null,
|
|
1184
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
1185
|
+
helperGroup: null,
|
|
904
1186
|
// Updates
|
|
905
1187
|
active: false,
|
|
906
1188
|
frames: 0,
|
|
@@ -986,7 +1268,15 @@ const createStore = (invalidate, advance) => {
|
|
|
986
1268
|
}
|
|
987
1269
|
if (camera !== oldCamera) {
|
|
988
1270
|
oldCamera = camera;
|
|
1271
|
+
const { rootScene } = rootStore.getState();
|
|
1272
|
+
if (camera && rootScene && !camera.parent) {
|
|
1273
|
+
rootScene.add(camera);
|
|
1274
|
+
}
|
|
989
1275
|
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1276
|
+
const currentState = rootStore.getState();
|
|
1277
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
1278
|
+
updateFrustum(camera, currentState.frustum);
|
|
1279
|
+
}
|
|
990
1280
|
}
|
|
991
1281
|
});
|
|
992
1282
|
rootStore.subscribe((state2) => invalidate(state2));
|
|
@@ -1045,18 +1335,18 @@ useLoader.clear = function(loader, input) {
|
|
|
1045
1335
|
};
|
|
1046
1336
|
useLoader.loader = getLoader;
|
|
1047
1337
|
|
|
1048
|
-
var __defProp$
|
|
1049
|
-
var __defNormalProp$
|
|
1050
|
-
var __publicField$
|
|
1338
|
+
var __defProp$2 = Object.defineProperty;
|
|
1339
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1340
|
+
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1051
1341
|
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1052
1342
|
class PhaseGraph {
|
|
1053
1343
|
constructor() {
|
|
1054
1344
|
/** Ordered list of phase nodes */
|
|
1055
|
-
__publicField$
|
|
1345
|
+
__publicField$2(this, "phases", []);
|
|
1056
1346
|
/** Quick lookup by name */
|
|
1057
|
-
__publicField$
|
|
1347
|
+
__publicField$2(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1058
1348
|
/** Cached ordered names (invalidated on changes) */
|
|
1059
|
-
__publicField$
|
|
1349
|
+
__publicField$2(this, "orderedNamesCache", null);
|
|
1060
1350
|
this.initializeDefaultPhases();
|
|
1061
1351
|
}
|
|
1062
1352
|
//* Initialization --------------------------------
|
|
@@ -1083,8 +1373,9 @@ class PhaseGraph {
|
|
|
1083
1373
|
const node = { name, isAutoGenerated: false };
|
|
1084
1374
|
let insertIndex = this.phases.length;
|
|
1085
1375
|
const targetIndex = this.getPhaseIndex(before ?? after);
|
|
1086
|
-
if (targetIndex !== -1)
|
|
1087
|
-
|
|
1376
|
+
if (targetIndex !== -1) {
|
|
1377
|
+
insertIndex = before ? targetIndex : targetIndex + 1;
|
|
1378
|
+
} else {
|
|
1088
1379
|
const constraintType = before ? "before" : "after";
|
|
1089
1380
|
console.warn(`[useFrame] Phase "${before ?? after}" not found for '${constraintType}' constraint`);
|
|
1090
1381
|
}
|
|
@@ -1312,9 +1603,9 @@ function resetJobTiming(job) {
|
|
|
1312
1603
|
job.lastRun = void 0;
|
|
1313
1604
|
}
|
|
1314
1605
|
|
|
1315
|
-
var __defProp = Object.defineProperty;
|
|
1316
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1317
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1606
|
+
var __defProp$1 = Object.defineProperty;
|
|
1607
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1608
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1318
1609
|
const hmrData = (() => {
|
|
1319
1610
|
if (typeof process !== "undefined" && process.env.NODE_ENV === "test") return void 0;
|
|
1320
1611
|
if (typeof import_meta_hot !== "undefined") return import_meta_hot;
|
|
@@ -1328,9 +1619,9 @@ const _Scheduler = class _Scheduler {
|
|
|
1328
1619
|
//* Constructor ================================
|
|
1329
1620
|
constructor() {
|
|
1330
1621
|
//* Critical State ================================
|
|
1331
|
-
__publicField(this, "roots", /* @__PURE__ */ new Map());
|
|
1332
|
-
__publicField(this, "phaseGraph");
|
|
1333
|
-
__publicField(this, "loopState", {
|
|
1622
|
+
__publicField$1(this, "roots", /* @__PURE__ */ new Map());
|
|
1623
|
+
__publicField$1(this, "phaseGraph");
|
|
1624
|
+
__publicField$1(this, "loopState", {
|
|
1334
1625
|
running: false,
|
|
1335
1626
|
rafHandle: null,
|
|
1336
1627
|
lastTime: null,
|
|
@@ -1339,17 +1630,21 @@ const _Scheduler = class _Scheduler {
|
|
|
1339
1630
|
elapsedTime: 0,
|
|
1340
1631
|
createdAt: performance.now()
|
|
1341
1632
|
});
|
|
1342
|
-
__publicField(this, "stoppedTime", 0);
|
|
1633
|
+
__publicField$1(this, "stoppedTime", 0);
|
|
1343
1634
|
//* Private State ================================
|
|
1344
|
-
__publicField(this, "nextRootIndex", 0);
|
|
1345
|
-
__publicField(this, "globalBeforeJobs", /* @__PURE__ */ new Map());
|
|
1346
|
-
__publicField(this, "globalAfterJobs", /* @__PURE__ */ new Map());
|
|
1347
|
-
__publicField(this, "nextGlobalIndex", 0);
|
|
1348
|
-
__publicField(this, "idleCallbacks", /* @__PURE__ */ new Set());
|
|
1349
|
-
__publicField(this, "nextJobIndex", 0);
|
|
1350
|
-
__publicField(this, "jobStateListeners", /* @__PURE__ */ new Map());
|
|
1351
|
-
__publicField(this, "pendingFrames", 0);
|
|
1352
|
-
__publicField(this, "_frameloop", "always");
|
|
1635
|
+
__publicField$1(this, "nextRootIndex", 0);
|
|
1636
|
+
__publicField$1(this, "globalBeforeJobs", /* @__PURE__ */ new Map());
|
|
1637
|
+
__publicField$1(this, "globalAfterJobs", /* @__PURE__ */ new Map());
|
|
1638
|
+
__publicField$1(this, "nextGlobalIndex", 0);
|
|
1639
|
+
__publicField$1(this, "idleCallbacks", /* @__PURE__ */ new Set());
|
|
1640
|
+
__publicField$1(this, "nextJobIndex", 0);
|
|
1641
|
+
__publicField$1(this, "jobStateListeners", /* @__PURE__ */ new Map());
|
|
1642
|
+
__publicField$1(this, "pendingFrames", 0);
|
|
1643
|
+
__publicField$1(this, "_frameloop", "always");
|
|
1644
|
+
//* Independent Mode & Error Handling State ================================
|
|
1645
|
+
__publicField$1(this, "_independent", false);
|
|
1646
|
+
__publicField$1(this, "errorHandler", null);
|
|
1647
|
+
__publicField$1(this, "rootReadyCallbacks", /* @__PURE__ */ new Set());
|
|
1353
1648
|
//* Core Loop Execution Methods ================================
|
|
1354
1649
|
/**
|
|
1355
1650
|
* Main RAF loop callback.
|
|
@@ -1358,7 +1653,7 @@ const _Scheduler = class _Scheduler {
|
|
|
1358
1653
|
* @returns {void}
|
|
1359
1654
|
* @private
|
|
1360
1655
|
*/
|
|
1361
|
-
__publicField(this, "loop", (timestamp) => {
|
|
1656
|
+
__publicField$1(this, "loop", (timestamp) => {
|
|
1362
1657
|
if (!this.loopState.running) return;
|
|
1363
1658
|
this.executeFrame(timestamp);
|
|
1364
1659
|
if (this._frameloop === "demand") {
|
|
@@ -1372,6 +1667,12 @@ const _Scheduler = class _Scheduler {
|
|
|
1372
1667
|
});
|
|
1373
1668
|
this.phaseGraph = new PhaseGraph();
|
|
1374
1669
|
}
|
|
1670
|
+
static get instance() {
|
|
1671
|
+
return globalThis[_Scheduler.INSTANCE_KEY] ?? null;
|
|
1672
|
+
}
|
|
1673
|
+
static set instance(value) {
|
|
1674
|
+
globalThis[_Scheduler.INSTANCE_KEY] = value;
|
|
1675
|
+
}
|
|
1375
1676
|
/**
|
|
1376
1677
|
* Get the global scheduler instance (creates if doesn't exist).
|
|
1377
1678
|
* Uses HMR data to preserve instance across hot reloads.
|
|
@@ -1420,29 +1721,43 @@ const _Scheduler = class _Scheduler {
|
|
|
1420
1721
|
get isRunning() {
|
|
1421
1722
|
return this.loopState.running;
|
|
1422
1723
|
}
|
|
1724
|
+
get isReady() {
|
|
1725
|
+
return this.roots.size > 0;
|
|
1726
|
+
}
|
|
1727
|
+
get independent() {
|
|
1728
|
+
return this._independent;
|
|
1729
|
+
}
|
|
1730
|
+
set independent(value) {
|
|
1731
|
+
this._independent = value;
|
|
1732
|
+
if (value) this.ensureDefaultRoot();
|
|
1733
|
+
}
|
|
1423
1734
|
//* Root Management Methods ================================
|
|
1424
1735
|
/**
|
|
1425
1736
|
* Register a root (Canvas) with the scheduler.
|
|
1426
1737
|
* The first root to register starts the RAF loop (if frameloop='always').
|
|
1427
1738
|
* @param {string} id - Unique identifier for this root
|
|
1428
|
-
* @param {
|
|
1739
|
+
* @param {RootOptions} [options] - Optional configuration with getState and onError callbacks
|
|
1429
1740
|
* @returns {() => void} Unsubscribe function to remove this root
|
|
1430
1741
|
*/
|
|
1431
|
-
registerRoot(id,
|
|
1742
|
+
registerRoot(id, options = {}) {
|
|
1432
1743
|
if (this.roots.has(id)) {
|
|
1433
1744
|
console.warn(`[Scheduler] Root "${id}" already registered`);
|
|
1434
1745
|
return () => this.unregisterRoot(id);
|
|
1435
1746
|
}
|
|
1436
1747
|
const entry = {
|
|
1437
1748
|
id,
|
|
1438
|
-
getState,
|
|
1749
|
+
getState: options.getState ?? (() => ({})),
|
|
1439
1750
|
jobs: /* @__PURE__ */ new Map(),
|
|
1440
1751
|
sortedJobs: [],
|
|
1441
1752
|
needsRebuild: false
|
|
1442
1753
|
};
|
|
1754
|
+
if (options.onError) {
|
|
1755
|
+
this.errorHandler = options.onError;
|
|
1756
|
+
}
|
|
1443
1757
|
this.roots.set(id, entry);
|
|
1444
|
-
if (this.roots.size === 1
|
|
1445
|
-
this.
|
|
1758
|
+
if (this.roots.size === 1) {
|
|
1759
|
+
this.notifyRootReady();
|
|
1760
|
+
if (this._frameloop === "always") this.start();
|
|
1446
1761
|
}
|
|
1447
1762
|
return () => this.unregisterRoot(id);
|
|
1448
1763
|
}
|
|
@@ -1462,7 +1777,60 @@ const _Scheduler = class _Scheduler {
|
|
|
1462
1777
|
this.roots.delete(id);
|
|
1463
1778
|
if (this.roots.size === 0) {
|
|
1464
1779
|
this.stop();
|
|
1780
|
+
this.errorHandler = null;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
/**
|
|
1784
|
+
* Subscribe to be notified when a root becomes available.
|
|
1785
|
+
* Fires immediately if a root already exists.
|
|
1786
|
+
* @param {() => void} callback - Function called when first root registers
|
|
1787
|
+
* @returns {() => void} Unsubscribe function
|
|
1788
|
+
*/
|
|
1789
|
+
onRootReady(callback) {
|
|
1790
|
+
if (this.roots.size > 0) {
|
|
1791
|
+
callback();
|
|
1792
|
+
return () => {
|
|
1793
|
+
};
|
|
1465
1794
|
}
|
|
1795
|
+
this.rootReadyCallbacks.add(callback);
|
|
1796
|
+
return () => this.rootReadyCallbacks.delete(callback);
|
|
1797
|
+
}
|
|
1798
|
+
/**
|
|
1799
|
+
* Notify all registered root-ready callbacks.
|
|
1800
|
+
* Called when the first root registers.
|
|
1801
|
+
* @returns {void}
|
|
1802
|
+
* @private
|
|
1803
|
+
*/
|
|
1804
|
+
notifyRootReady() {
|
|
1805
|
+
for (const cb of this.rootReadyCallbacks) {
|
|
1806
|
+
try {
|
|
1807
|
+
cb();
|
|
1808
|
+
} catch (error) {
|
|
1809
|
+
console.error("[Scheduler] Error in root-ready callback:", error);
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
this.rootReadyCallbacks.clear();
|
|
1813
|
+
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Ensure a default root exists for independent mode.
|
|
1816
|
+
* Creates a minimal root with no state provider.
|
|
1817
|
+
* @returns {void}
|
|
1818
|
+
* @private
|
|
1819
|
+
*/
|
|
1820
|
+
ensureDefaultRoot() {
|
|
1821
|
+
if (!this.roots.has("__default__")) {
|
|
1822
|
+
this.registerRoot("__default__");
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Trigger error handling for job errors.
|
|
1827
|
+
* Uses the bound error handler if available, otherwise logs to console.
|
|
1828
|
+
* @param {Error} error - The error to handle
|
|
1829
|
+
* @returns {void}
|
|
1830
|
+
*/
|
|
1831
|
+
triggerError(error) {
|
|
1832
|
+
if (this.errorHandler) this.errorHandler(error);
|
|
1833
|
+
else console.error("[Scheduler]", error);
|
|
1466
1834
|
}
|
|
1467
1835
|
//* Phase Management Methods ================================
|
|
1468
1836
|
/**
|
|
@@ -1822,9 +2190,9 @@ const _Scheduler = class _Scheduler {
|
|
|
1822
2190
|
const deltaMs = this.loopState.lastTime !== null ? now - this.loopState.lastTime : 0;
|
|
1823
2191
|
const delta = deltaMs / 1e3;
|
|
1824
2192
|
const elapsed = now - this.loopState.createdAt;
|
|
1825
|
-
const
|
|
2193
|
+
const providedState = root.getState?.() ?? {};
|
|
1826
2194
|
const frameState = {
|
|
1827
|
-
...
|
|
2195
|
+
...providedState,
|
|
1828
2196
|
time: now,
|
|
1829
2197
|
delta,
|
|
1830
2198
|
elapsed,
|
|
@@ -1834,6 +2202,7 @@ const _Scheduler = class _Scheduler {
|
|
|
1834
2202
|
job.callback(frameState, delta);
|
|
1835
2203
|
} catch (error) {
|
|
1836
2204
|
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2205
|
+
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
1837
2206
|
}
|
|
1838
2207
|
}
|
|
1839
2208
|
/**
|
|
@@ -1875,7 +2244,7 @@ const _Scheduler = class _Scheduler {
|
|
|
1875
2244
|
/**
|
|
1876
2245
|
* Execute all jobs for a single root in sorted order.
|
|
1877
2246
|
* Rebuilds sorted job list if needed, then dispatches each job.
|
|
1878
|
-
* Errors are caught and propagated
|
|
2247
|
+
* Errors are caught and propagated via triggerError.
|
|
1879
2248
|
* @param {RootEntry} root - The root entry to tick
|
|
1880
2249
|
* @param {number} timestamp - RAF timestamp in milliseconds
|
|
1881
2250
|
* @param {number} delta - Time since last frame in seconds
|
|
@@ -1887,10 +2256,9 @@ const _Scheduler = class _Scheduler {
|
|
|
1887
2256
|
root.sortedJobs = rebuildSortedJobs(root.jobs, this.phaseGraph);
|
|
1888
2257
|
root.needsRebuild = false;
|
|
1889
2258
|
}
|
|
1890
|
-
const
|
|
1891
|
-
if (!rootState) return;
|
|
2259
|
+
const providedState = root.getState?.() ?? {};
|
|
1892
2260
|
const frameState = {
|
|
1893
|
-
...
|
|
2261
|
+
...providedState,
|
|
1894
2262
|
time: timestamp,
|
|
1895
2263
|
delta,
|
|
1896
2264
|
elapsed: this.loopState.elapsedTime / 1e3,
|
|
@@ -1903,7 +2271,7 @@ const _Scheduler = class _Scheduler {
|
|
|
1903
2271
|
job.callback(frameState, delta);
|
|
1904
2272
|
} catch (error) {
|
|
1905
2273
|
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
1906
|
-
|
|
2274
|
+
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
1907
2275
|
}
|
|
1908
2276
|
}
|
|
1909
2277
|
}
|
|
@@ -1988,8 +2356,11 @@ const _Scheduler = class _Scheduler {
|
|
|
1988
2356
|
return /* @__PURE__ */ new Set([value]);
|
|
1989
2357
|
}
|
|
1990
2358
|
};
|
|
1991
|
-
//* Static State & Methods (
|
|
1992
|
-
|
|
2359
|
+
//* Static State & Methods (Singleton Usage) ================================
|
|
2360
|
+
//* Cross-Bundle Singleton Key ==============================
|
|
2361
|
+
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2362
|
+
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2363
|
+
__publicField$1(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
1993
2364
|
let Scheduler = _Scheduler;
|
|
1994
2365
|
const getScheduler = () => Scheduler.get();
|
|
1995
2366
|
if (hmrData) {
|
|
@@ -1997,11 +2368,9 @@ if (hmrData) {
|
|
|
1997
2368
|
}
|
|
1998
2369
|
|
|
1999
2370
|
function useFrame(callback, priorityOrOptions) {
|
|
2000
|
-
const store =
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2003
|
-
return state.internal.rootId;
|
|
2004
|
-
}, [store]);
|
|
2371
|
+
const store = React.useContext(context);
|
|
2372
|
+
const isInsideCanvas = store !== null;
|
|
2373
|
+
const scheduler = getScheduler();
|
|
2005
2374
|
const optionsKey = typeof priorityOrOptions === "number" ? `p:${priorityOrOptions}` : priorityOrOptions ? JSON.stringify({
|
|
2006
2375
|
id: priorityOrOptions.id,
|
|
2007
2376
|
phase: priorityOrOptions.phase,
|
|
@@ -2021,55 +2390,71 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
2021
2390
|
const isLegacyPriority = typeof priorityOrOptions === "number" && priorityOrOptions > 0;
|
|
2022
2391
|
useIsomorphicLayoutEffect(() => {
|
|
2023
2392
|
if (!callback) return;
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
if (isLegacyPriority) {
|
|
2028
|
-
state.internal.priority++;
|
|
2029
|
-
let parentRoot = state.previousRoot;
|
|
2030
|
-
while (parentRoot) {
|
|
2031
|
-
const parentState = parentRoot.getState();
|
|
2032
|
-
if (parentState?.internal) parentState.internal.priority++;
|
|
2033
|
-
parentRoot = parentState?.previousRoot;
|
|
2034
|
-
}
|
|
2035
|
-
notifyDepreciated({
|
|
2036
|
-
heading: "useFrame with numeric priority is deprecated",
|
|
2037
|
-
body: 'Using useFrame(callback, number) to control render order is deprecated.\n\nFor custom rendering, use: useFrame(callback, { phase: "render" })\nFor execution order within update phase, use: useFrame(callback, { priority: number })',
|
|
2038
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
2039
|
-
});
|
|
2040
|
-
}
|
|
2041
|
-
const wrappedCallback = (frameState, delta) => {
|
|
2042
|
-
const localState = store.getState();
|
|
2043
|
-
const mergedState = {
|
|
2044
|
-
...localState,
|
|
2045
|
-
time: frameState.time,
|
|
2046
|
-
delta: frameState.delta,
|
|
2047
|
-
elapsed: frameState.elapsed,
|
|
2048
|
-
frame: frameState.frame
|
|
2049
|
-
};
|
|
2050
|
-
callbackRef.current?.(mergedState, delta);
|
|
2051
|
-
};
|
|
2052
|
-
const unregister = scheduler.register(wrappedCallback, {
|
|
2053
|
-
id,
|
|
2054
|
-
rootId,
|
|
2055
|
-
...options
|
|
2056
|
-
});
|
|
2057
|
-
return () => {
|
|
2058
|
-
unregister();
|
|
2393
|
+
if (isInsideCanvas) {
|
|
2394
|
+
const state = store.getState();
|
|
2395
|
+
const rootId = state.internal.rootId;
|
|
2059
2396
|
if (isLegacyPriority) {
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2397
|
+
state.internal.priority++;
|
|
2398
|
+
let parentRoot = state.previousRoot;
|
|
2399
|
+
while (parentRoot) {
|
|
2400
|
+
const parentState = parentRoot.getState();
|
|
2401
|
+
if (parentState?.internal) parentState.internal.priority++;
|
|
2402
|
+
parentRoot = parentState?.previousRoot;
|
|
2403
|
+
}
|
|
2404
|
+
notifyDepreciated({
|
|
2405
|
+
heading: "useFrame with numeric priority is deprecated",
|
|
2406
|
+
body: 'Using useFrame(callback, number) to control render order is deprecated.\n\nFor custom rendering, use: useFrame(callback, { phase: "render" })\nFor execution order within update phase, use: useFrame(callback, { priority: number })',
|
|
2407
|
+
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
const wrappedCallback = (frameState, delta) => {
|
|
2411
|
+
const localState = store.getState();
|
|
2412
|
+
const mergedState = {
|
|
2413
|
+
...localState,
|
|
2414
|
+
time: frameState.time,
|
|
2415
|
+
delta: frameState.delta,
|
|
2416
|
+
elapsed: frameState.elapsed,
|
|
2417
|
+
frame: frameState.frame
|
|
2418
|
+
};
|
|
2419
|
+
callbackRef.current?.(mergedState, delta);
|
|
2420
|
+
};
|
|
2421
|
+
const unregister = scheduler.register(wrappedCallback, {
|
|
2422
|
+
id,
|
|
2423
|
+
rootId,
|
|
2424
|
+
...options
|
|
2425
|
+
});
|
|
2426
|
+
return () => {
|
|
2427
|
+
unregister();
|
|
2428
|
+
if (isLegacyPriority) {
|
|
2429
|
+
const currentState = store.getState();
|
|
2430
|
+
if (currentState.internal) {
|
|
2431
|
+
currentState.internal.priority--;
|
|
2432
|
+
let parentRoot = currentState.previousRoot;
|
|
2433
|
+
while (parentRoot) {
|
|
2434
|
+
const parentState = parentRoot.getState();
|
|
2435
|
+
if (parentState?.internal) parentState.internal.priority--;
|
|
2436
|
+
parentRoot = parentState?.previousRoot;
|
|
2437
|
+
}
|
|
2068
2438
|
}
|
|
2069
2439
|
}
|
|
2440
|
+
};
|
|
2441
|
+
} else {
|
|
2442
|
+
const registerOutside = () => {
|
|
2443
|
+
return scheduler.register((state, delta) => callbackRef.current?.(state, delta), { id, ...options });
|
|
2444
|
+
};
|
|
2445
|
+
if (scheduler.independent || scheduler.isReady) {
|
|
2446
|
+
return registerOutside();
|
|
2070
2447
|
}
|
|
2071
|
-
|
|
2072
|
-
|
|
2448
|
+
let unregisterJob = null;
|
|
2449
|
+
const unsubReady = scheduler.onRootReady(() => {
|
|
2450
|
+
unregisterJob = registerOutside();
|
|
2451
|
+
});
|
|
2452
|
+
return () => {
|
|
2453
|
+
unsubReady();
|
|
2454
|
+
unregisterJob?.();
|
|
2455
|
+
};
|
|
2456
|
+
}
|
|
2457
|
+
}, [store, scheduler, id, optionsKey, isLegacyPriority, isInsideCanvas]);
|
|
2073
2458
|
const isPaused = React.useSyncExternalStore(
|
|
2074
2459
|
// Subscribe function
|
|
2075
2460
|
React.useCallback(
|
|
@@ -2084,7 +2469,7 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
2084
2469
|
React.useCallback(() => false, [])
|
|
2085
2470
|
);
|
|
2086
2471
|
const controls = React.useMemo(() => {
|
|
2087
|
-
const
|
|
2472
|
+
const scheduler2 = getScheduler();
|
|
2088
2473
|
return {
|
|
2089
2474
|
/** The job's unique ID */
|
|
2090
2475
|
id,
|
|
@@ -2092,7 +2477,7 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
2092
2477
|
* Access to the global scheduler for frame loop control.
|
|
2093
2478
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
2094
2479
|
*/
|
|
2095
|
-
scheduler,
|
|
2480
|
+
scheduler: scheduler2,
|
|
2096
2481
|
/**
|
|
2097
2482
|
* Manually step this job only.
|
|
2098
2483
|
* Bypasses FPS limiting - always runs.
|
|
@@ -2340,6 +2725,16 @@ function useTextures() {
|
|
|
2340
2725
|
}, [store]);
|
|
2341
2726
|
}
|
|
2342
2727
|
|
|
2728
|
+
function useRenderTarget(width, height, options) {
|
|
2729
|
+
const isLegacy = useThree((s) => s.isLegacy);
|
|
2730
|
+
const size = useThree((s) => s.size);
|
|
2731
|
+
return useMemo(() => {
|
|
2732
|
+
const w = width ?? size.width;
|
|
2733
|
+
const h = height ?? size.height;
|
|
2734
|
+
return new RenderTarget(w, h, options);
|
|
2735
|
+
}, [width, height, size.width, size.height, options, isLegacy]);
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2343
2738
|
function useStore() {
|
|
2344
2739
|
const store = useContext(context);
|
|
2345
2740
|
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
@@ -2391,24 +2786,14 @@ function advance(timestamp, runGlobalEffects = true, state, frame) {
|
|
|
2391
2786
|
getScheduler().step(timestamp);
|
|
2392
2787
|
}
|
|
2393
2788
|
|
|
2394
|
-
const version = "10.0.0-alpha.
|
|
2789
|
+
const version = "10.0.0-alpha.2";
|
|
2395
2790
|
const packageData = {
|
|
2396
2791
|
version: version};
|
|
2397
2792
|
|
|
2398
2793
|
function Xb(Tt) {
|
|
2399
2794
|
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
2400
2795
|
}
|
|
2401
|
-
var Rm = { exports: {} }, Og = { exports: {} };
|
|
2402
|
-
/**
|
|
2403
|
-
* @license React
|
|
2404
|
-
* react-reconciler.production.js
|
|
2405
|
-
*
|
|
2406
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2407
|
-
*
|
|
2408
|
-
* This source code is licensed under the MIT license found in the
|
|
2409
|
-
* LICENSE file in the root directory of this source tree.
|
|
2410
|
-
*/
|
|
2411
|
-
var _b;
|
|
2796
|
+
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
2412
2797
|
function Kb() {
|
|
2413
2798
|
return _b || (_b = 1, (function(Tt) {
|
|
2414
2799
|
Tt.exports = function(m) {
|
|
@@ -3480,7 +3865,6 @@ Error generating stack: ` + l.message + `
|
|
|
3480
3865
|
if (J === cl || J === jc) throw J;
|
|
3481
3866
|
var Ge = Yn(29, J, null, P.mode);
|
|
3482
3867
|
return Ge.lanes = H, Ge.return = P, Ge;
|
|
3483
|
-
} finally {
|
|
3484
3868
|
}
|
|
3485
3869
|
};
|
|
3486
3870
|
}
|
|
@@ -4134,7 +4518,6 @@ Error generating stack: ` + l.message + `
|
|
|
4134
4518
|
var h = r.lastRenderedState, y = d(h, a);
|
|
4135
4519
|
if (c.hasEagerState = true, c.eagerState = y, jn(y, h)) return go(t, r, c, 0), Ne === null && Bn(), false;
|
|
4136
4520
|
} catch {
|
|
4137
|
-
} finally {
|
|
4138
4521
|
}
|
|
4139
4522
|
if (a = yo(t, r, c, l), a !== null) return nt(a, t, l), ns(a, r, l), true;
|
|
4140
4523
|
}
|
|
@@ -6555,10 +6938,7 @@ Error generating stack: ` + l.message + `
|
|
|
6555
6938
|
function vr(t, r) {
|
|
6556
6939
|
Sf(t, r), (t = t.alternate) && Sf(t, r);
|
|
6557
6940
|
}
|
|
6558
|
-
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");
|
|
6559
|
-
var gc = Symbol.for("react.activity");
|
|
6560
|
-
var $r = Symbol.for("react.memo_cache_sentinel");
|
|
6561
|
-
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;
|
|
6941
|
+
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;
|
|
6562
6942
|
m.cloneMutableInstance;
|
|
6563
6943
|
var yc = m.appendInitialChild, Kp = m.finalizeInitialChildren, Rs = m.shouldSetTextContent, bc = m.createTextInstance;
|
|
6564
6944
|
m.cloneMutableTextInstance;
|
|
@@ -6927,17 +7307,7 @@ No matching component was found for:
|
|
|
6927
7307
|
}, Tt.exports.default = Tt.exports, Object.defineProperty(Tt.exports, "__esModule", { value: true });
|
|
6928
7308
|
})(Og)), Og.exports;
|
|
6929
7309
|
}
|
|
6930
|
-
var Mg = { exports: {} };
|
|
6931
|
-
/**
|
|
6932
|
-
* @license React
|
|
6933
|
-
* react-reconciler.development.js
|
|
6934
|
-
*
|
|
6935
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
6936
|
-
*
|
|
6937
|
-
* This source code is licensed under the MIT license found in the
|
|
6938
|
-
* LICENSE file in the root directory of this source tree.
|
|
6939
|
-
*/
|
|
6940
|
-
var Rb;
|
|
7310
|
+
var Mg = { exports: {} }, Rb;
|
|
6941
7311
|
function e0() {
|
|
6942
7312
|
return Rb || (Rb = 1, (function(Tt) {
|
|
6943
7313
|
process.env.NODE_ENV !== "production" && (Tt.exports = function(m) {
|
|
@@ -12704,10 +13074,7 @@ Check the render method of %s.`, G(di) || "Unknown")), i = zo(n), i.payload = {
|
|
|
12704
13074
|
function Ic() {
|
|
12705
13075
|
return di;
|
|
12706
13076
|
}
|
|
12707
|
-
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");
|
|
12708
|
-
var Ds = Symbol.for("react.activity");
|
|
12709
|
-
var Bh = Symbol.for("react.memo_cache_sentinel");
|
|
12710
|
-
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;
|
|
13077
|
+
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;
|
|
12711
13078
|
m.cloneMutableInstance;
|
|
12712
13079
|
var bn = m.appendInitialChild, Ue = m.finalizeInitialChildren, ue = m.shouldSetTextContent, Do = m.createTextInstance;
|
|
12713
13080
|
m.cloneMutableTextInstance;
|
|
@@ -13675,15 +14042,6 @@ function n0() {
|
|
|
13675
14042
|
var t0 = n0();
|
|
13676
14043
|
const r0 = Xb(t0);
|
|
13677
14044
|
|
|
13678
|
-
/**
|
|
13679
|
-
* @license React
|
|
13680
|
-
* react-reconciler-constants.production.js
|
|
13681
|
-
*
|
|
13682
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
13683
|
-
*
|
|
13684
|
-
* This source code is licensed under the MIT license found in the
|
|
13685
|
-
* LICENSE file in the root directory of this source tree.
|
|
13686
|
-
*/
|
|
13687
14045
|
const t = 1, o = 8, r = 32, e = 2;
|
|
13688
14046
|
|
|
13689
14047
|
function createReconciler(config) {
|
|
@@ -13692,7 +14050,8 @@ function createReconciler(config) {
|
|
|
13692
14050
|
return reconciler2;
|
|
13693
14051
|
}
|
|
13694
14052
|
const NoEventPriority = 0;
|
|
13695
|
-
const
|
|
14053
|
+
const R3F_CATALOGUE = Symbol.for("@react-three/fiber.catalogue");
|
|
14054
|
+
const catalogue = globalThis[R3F_CATALOGUE] ?? (globalThis[R3F_CATALOGUE] = {});
|
|
13696
14055
|
const PREFIX_REGEX = /^three(?=[A-Z])/;
|
|
13697
14056
|
const toPascalCase = (type) => `${type[0].toUpperCase()}${type.slice(1)}`;
|
|
13698
14057
|
let i = 0;
|
|
@@ -13709,10 +14068,11 @@ function extend(objects) {
|
|
|
13709
14068
|
function validateInstance(type, props) {
|
|
13710
14069
|
const name = toPascalCase(type);
|
|
13711
14070
|
const target = catalogue[name];
|
|
13712
|
-
if (type !== "primitive" && !target)
|
|
14071
|
+
if (type !== "primitive" && !target) {
|
|
13713
14072
|
throw new Error(
|
|
13714
14073
|
`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`
|
|
13715
14074
|
);
|
|
14075
|
+
}
|
|
13716
14076
|
if (type === "primitive" && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`);
|
|
13717
14077
|
if (props.args !== void 0 && !Array.isArray(props.args)) throw new Error("R3F: The args prop must be an array!");
|
|
13718
14078
|
}
|
|
@@ -14163,14 +14523,14 @@ function createRoot(canvas) {
|
|
|
14163
14523
|
if (!prevRoot) _roots.set(canvas, { fiber, store });
|
|
14164
14524
|
let onCreated;
|
|
14165
14525
|
let lastCamera;
|
|
14166
|
-
|
|
14526
|
+
const lastConfiguredProps = {};
|
|
14167
14527
|
let configured = false;
|
|
14168
14528
|
let pending = null;
|
|
14169
14529
|
return {
|
|
14170
14530
|
async configure(props = {}) {
|
|
14171
14531
|
let resolve;
|
|
14172
14532
|
pending = new Promise((_resolve) => resolve = _resolve);
|
|
14173
|
-
|
|
14533
|
+
const {
|
|
14174
14534
|
gl: glConfig,
|
|
14175
14535
|
renderer: rendererConfig,
|
|
14176
14536
|
size: propsSize,
|
|
@@ -14190,9 +14550,12 @@ function createRoot(canvas) {
|
|
|
14190
14550
|
camera: cameraOptions,
|
|
14191
14551
|
onPointerMissed,
|
|
14192
14552
|
onDragOverMissed,
|
|
14193
|
-
onDropMissed
|
|
14553
|
+
onDropMissed,
|
|
14554
|
+
autoUpdateFrustum = true,
|
|
14555
|
+
occlusion = false,
|
|
14556
|
+
_sizeProps
|
|
14194
14557
|
} = props;
|
|
14195
|
-
|
|
14558
|
+
const state = store.getState();
|
|
14196
14559
|
const defaultGPUProps = {
|
|
14197
14560
|
canvas
|
|
14198
14561
|
};
|
|
@@ -14207,7 +14570,9 @@ function createRoot(canvas) {
|
|
|
14207
14570
|
let renderer = state.internal.actualRenderer;
|
|
14208
14571
|
if (!state.internal.actualRenderer) {
|
|
14209
14572
|
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, WebGPURenderer);
|
|
14210
|
-
|
|
14573
|
+
if (!renderer.hasInitialized?.()) {
|
|
14574
|
+
await renderer.init();
|
|
14575
|
+
}
|
|
14211
14576
|
const backend = renderer.backend;
|
|
14212
14577
|
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
14213
14578
|
state.internal.actualRenderer = renderer;
|
|
@@ -14217,8 +14582,9 @@ function createRoot(canvas) {
|
|
|
14217
14582
|
if (!raycaster) state.set({ raycaster: raycaster = new Raycaster() });
|
|
14218
14583
|
const { params, ...options } = raycastOptions || {};
|
|
14219
14584
|
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options });
|
|
14220
|
-
if (!is.equ(params, raycaster.params, shallowLoose))
|
|
14585
|
+
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
14221
14586
|
applyProps(raycaster, { params: { ...raycaster.params, ...params } });
|
|
14587
|
+
}
|
|
14222
14588
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
14223
14589
|
lastCamera = cameraOptions;
|
|
14224
14590
|
const isCamera = cameraOptions?.isCamera;
|
|
@@ -14255,6 +14621,8 @@ function createRoot(canvas) {
|
|
|
14255
14621
|
rootScene: scene,
|
|
14256
14622
|
internal: { ...prev.internal, container: scene }
|
|
14257
14623
|
}));
|
|
14624
|
+
const camera = state.camera;
|
|
14625
|
+
if (camera && !camera.parent) scene.add(camera);
|
|
14258
14626
|
}
|
|
14259
14627
|
if (events && !state.events.handlers) {
|
|
14260
14628
|
state.set({ events: events(store) });
|
|
@@ -14267,9 +14635,14 @@ function createRoot(canvas) {
|
|
|
14267
14635
|
wasEnabled = enabled;
|
|
14268
14636
|
});
|
|
14269
14637
|
}
|
|
14638
|
+
if (_sizeProps !== void 0) {
|
|
14639
|
+
state.set({ _sizeProps });
|
|
14640
|
+
}
|
|
14270
14641
|
const size = computeInitialSize(canvas, propsSize);
|
|
14271
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
14642
|
+
if (!state._sizeImperative && !is.equ(size, state.size, shallowLoose)) {
|
|
14643
|
+
const wasImperative = state._sizeImperative;
|
|
14272
14644
|
state.setSize(size.width, size.height, size.top, size.left);
|
|
14645
|
+
if (!wasImperative) state.set({ _sizeImperative: false });
|
|
14273
14646
|
}
|
|
14274
14647
|
if (dpr !== void 0 && !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose)) {
|
|
14275
14648
|
state.setDpr(dpr);
|
|
@@ -14282,6 +14655,10 @@ function createRoot(canvas) {
|
|
|
14282
14655
|
if (!state.onPointerMissed) state.set({ onPointerMissed });
|
|
14283
14656
|
if (!state.onDragOverMissed) state.set({ onDragOverMissed });
|
|
14284
14657
|
if (!state.onDropMissed) state.set({ onDropMissed });
|
|
14658
|
+
if (state.autoUpdateFrustum !== autoUpdateFrustum) state.set({ autoUpdateFrustum });
|
|
14659
|
+
if (occlusion && !state.internal.occlusionEnabled) {
|
|
14660
|
+
enableOcclusion(store);
|
|
14661
|
+
}
|
|
14285
14662
|
if (performance && !is.equ(performance, lastConfiguredProps.performance, shallowLoose)) {
|
|
14286
14663
|
state.set((state2) => ({ performance: { ...state2.performance, ...performance } }));
|
|
14287
14664
|
lastConfiguredProps.performance = performance;
|
|
@@ -14335,15 +14712,17 @@ function createRoot(canvas) {
|
|
|
14335
14712
|
} else if (is.obj(shadows)) {
|
|
14336
14713
|
Object.assign(renderer.shadowMap, shadows);
|
|
14337
14714
|
}
|
|
14338
|
-
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type)
|
|
14715
|
+
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
14339
14716
|
renderer.shadowMap.needsUpdate = true;
|
|
14717
|
+
}
|
|
14340
14718
|
}
|
|
14341
14719
|
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
14342
14720
|
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
14343
14721
|
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
14344
14722
|
}
|
|
14345
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose))
|
|
14723
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
14346
14724
|
applyProps(renderer, glConfig);
|
|
14725
|
+
}
|
|
14347
14726
|
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
14348
14727
|
const currentRenderer = state.renderer;
|
|
14349
14728
|
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
@@ -14354,7 +14733,37 @@ function createRoot(canvas) {
|
|
|
14354
14733
|
const rootId = state.internal.rootId;
|
|
14355
14734
|
if (!rootId) {
|
|
14356
14735
|
const newRootId = scheduler.generateRootId();
|
|
14357
|
-
const unregisterRoot = scheduler.registerRoot(newRootId,
|
|
14736
|
+
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14737
|
+
getState: () => store.getState(),
|
|
14738
|
+
onError: (err) => store.getState().setError(err)
|
|
14739
|
+
});
|
|
14740
|
+
const unregisterFrustum = scheduler.register(
|
|
14741
|
+
() => {
|
|
14742
|
+
const state2 = store.getState();
|
|
14743
|
+
if (state2.autoUpdateFrustum && state2.camera) {
|
|
14744
|
+
updateFrustum(state2.camera, state2.frustum);
|
|
14745
|
+
}
|
|
14746
|
+
},
|
|
14747
|
+
{
|
|
14748
|
+
id: `${newRootId}_frustum`,
|
|
14749
|
+
rootId: newRootId,
|
|
14750
|
+
phase: "preRender",
|
|
14751
|
+
system: true
|
|
14752
|
+
}
|
|
14753
|
+
);
|
|
14754
|
+
const unregisterVisibility = scheduler.register(
|
|
14755
|
+
() => {
|
|
14756
|
+
const state2 = store.getState();
|
|
14757
|
+
checkVisibility(state2);
|
|
14758
|
+
},
|
|
14759
|
+
{
|
|
14760
|
+
id: `${newRootId}_visibility`,
|
|
14761
|
+
rootId: newRootId,
|
|
14762
|
+
phase: "preRender",
|
|
14763
|
+
system: true,
|
|
14764
|
+
after: `${newRootId}_frustum`
|
|
14765
|
+
}
|
|
14766
|
+
);
|
|
14358
14767
|
const unregisterRender = scheduler.register(
|
|
14359
14768
|
() => {
|
|
14360
14769
|
const state2 = store.getState();
|
|
@@ -14382,6 +14791,8 @@ function createRoot(canvas) {
|
|
|
14382
14791
|
rootId: newRootId,
|
|
14383
14792
|
unregisterRoot: () => {
|
|
14384
14793
|
unregisterRoot();
|
|
14794
|
+
unregisterFrustum();
|
|
14795
|
+
unregisterVisibility();
|
|
14385
14796
|
unregisterRender();
|
|
14386
14797
|
},
|
|
14387
14798
|
scheduler
|
|
@@ -14439,6 +14850,7 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14439
14850
|
const unregisterRoot = state.internal.unregisterRoot;
|
|
14440
14851
|
if (unregisterRoot) unregisterRoot();
|
|
14441
14852
|
state.events.disconnect?.();
|
|
14853
|
+
cleanupHelperGroup(root.store);
|
|
14442
14854
|
renderer?.renderLists?.dispose?.();
|
|
14443
14855
|
renderer?.forceContextLoss?.();
|
|
14444
14856
|
if (renderer?.xr) state.xr.disconnect();
|
|
@@ -14578,6 +14990,9 @@ function CanvasImpl({
|
|
|
14578
14990
|
onDragOverMissed,
|
|
14579
14991
|
onDropMissed,
|
|
14580
14992
|
onCreated,
|
|
14993
|
+
hmr,
|
|
14994
|
+
width,
|
|
14995
|
+
height,
|
|
14581
14996
|
...props
|
|
14582
14997
|
}) {
|
|
14583
14998
|
React.useMemo(() => extend(THREE), []);
|
|
@@ -14598,7 +15013,16 @@ function CanvasImpl({
|
|
|
14598
15013
|
};
|
|
14599
15014
|
}, [resize, hasInitialSizeRef.current]);
|
|
14600
15015
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
14601
|
-
|
|
15016
|
+
const effectiveSize = React.useMemo(
|
|
15017
|
+
() => ({
|
|
15018
|
+
width: width ?? containerRect.width,
|
|
15019
|
+
height: height ?? containerRect.height,
|
|
15020
|
+
top: containerRect.top,
|
|
15021
|
+
left: containerRect.left
|
|
15022
|
+
}),
|
|
15023
|
+
[width, height, containerRect]
|
|
15024
|
+
);
|
|
15025
|
+
if (!hasInitialSizeRef.current && effectiveSize.width > 0 && effectiveSize.height > 0) {
|
|
14602
15026
|
hasInitialSizeRef.current = true;
|
|
14603
15027
|
}
|
|
14604
15028
|
const canvasRef = React.useRef(null);
|
|
@@ -14617,8 +15041,23 @@ function CanvasImpl({
|
|
|
14617
15041
|
useIsomorphicLayoutEffect(() => {
|
|
14618
15042
|
effectActiveRef.current = true;
|
|
14619
15043
|
const canvas = canvasRef.current;
|
|
14620
|
-
if (
|
|
14621
|
-
if (!root.current)
|
|
15044
|
+
if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
|
|
15045
|
+
if (!root.current) {
|
|
15046
|
+
root.current = createRoot(canvas);
|
|
15047
|
+
notifyAlpha({
|
|
15048
|
+
message: "React Three Fiber v10 is in ALPHA - expect breaking changes",
|
|
15049
|
+
link: "https://github.com/pmndrs/react-three-fiber/discussions"
|
|
15050
|
+
});
|
|
15051
|
+
const rootEntry = _roots.get(canvas);
|
|
15052
|
+
if (rootEntry?.store) {
|
|
15053
|
+
if (unsubscribeErrorRef.current) unsubscribeErrorRef.current();
|
|
15054
|
+
unsubscribeErrorRef.current = rootEntry.store.subscribe((state) => {
|
|
15055
|
+
if (state.error && effectActiveRef.current) {
|
|
15056
|
+
setError(state.error);
|
|
15057
|
+
}
|
|
15058
|
+
});
|
|
15059
|
+
}
|
|
15060
|
+
}
|
|
14622
15061
|
async function run() {
|
|
14623
15062
|
if (!effectActiveRef.current || !root.current) return;
|
|
14624
15063
|
await root.current.configure({
|
|
@@ -14636,7 +15075,9 @@ function CanvasImpl({
|
|
|
14636
15075
|
performance,
|
|
14637
15076
|
raycaster,
|
|
14638
15077
|
camera,
|
|
14639
|
-
size:
|
|
15078
|
+
size: effectiveSize,
|
|
15079
|
+
// Store size props for reset functionality
|
|
15080
|
+
_sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
|
|
14640
15081
|
// Pass mutable reference to onPointerMissed so it's free to update
|
|
14641
15082
|
onPointerMissed: (...args) => handlePointerMissed.current?.(...args),
|
|
14642
15083
|
onDragOverMissed: (...args) => handleDragOverMissed.current?.(...args),
|
|
@@ -14659,15 +15100,9 @@ function CanvasImpl({
|
|
|
14659
15100
|
}
|
|
14660
15101
|
});
|
|
14661
15102
|
if (!effectActiveRef.current || !root.current) return;
|
|
14662
|
-
|
|
15103
|
+
root.current.render(
|
|
14663
15104
|
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsx(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: children ?? null }) }) })
|
|
14664
15105
|
);
|
|
14665
|
-
if (unsubscribeErrorRef.current) unsubscribeErrorRef.current();
|
|
14666
|
-
unsubscribeErrorRef.current = store.subscribe((state) => {
|
|
14667
|
-
if (state.error && effectActiveRef.current) {
|
|
14668
|
-
setError(state.error);
|
|
14669
|
-
}
|
|
14670
|
-
});
|
|
14671
15106
|
}
|
|
14672
15107
|
run();
|
|
14673
15108
|
}
|
|
@@ -14688,6 +15123,33 @@ function CanvasImpl({
|
|
|
14688
15123
|
};
|
|
14689
15124
|
}
|
|
14690
15125
|
}, []);
|
|
15126
|
+
React.useEffect(() => {
|
|
15127
|
+
if (hmr === false) return;
|
|
15128
|
+
const canvas = canvasRef.current;
|
|
15129
|
+
if (!canvas) return;
|
|
15130
|
+
const handleHMR = () => {
|
|
15131
|
+
const rootEntry = _roots.get(canvas);
|
|
15132
|
+
if (rootEntry?.store) {
|
|
15133
|
+
rootEntry.store.setState((state) => ({
|
|
15134
|
+
nodes: {},
|
|
15135
|
+
uniforms: {},
|
|
15136
|
+
_hmrVersion: state._hmrVersion + 1
|
|
15137
|
+
}));
|
|
15138
|
+
}
|
|
15139
|
+
};
|
|
15140
|
+
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
15141
|
+
const hot = import.meta.hot;
|
|
15142
|
+
hot.on("vite:afterUpdate", handleHMR);
|
|
15143
|
+
return () => hot.dispose?.(() => {
|
|
15144
|
+
});
|
|
15145
|
+
}
|
|
15146
|
+
if (typeof module !== "undefined" && module.hot) {
|
|
15147
|
+
const hot = module.hot;
|
|
15148
|
+
hot.addStatusHandler((status) => {
|
|
15149
|
+
if (status === "idle") handleHMR();
|
|
15150
|
+
});
|
|
15151
|
+
}
|
|
15152
|
+
}, [hmr]);
|
|
14691
15153
|
const pointerEvents = eventSource ? "none" : "auto";
|
|
14692
15154
|
return /* @__PURE__ */ jsx(
|
|
14693
15155
|
"div",
|
|
@@ -14710,6 +15172,72 @@ function Canvas(props) {
|
|
|
14710
15172
|
return /* @__PURE__ */ jsx(FiberProvider, { children: /* @__PURE__ */ jsx(CanvasImpl, { ...props }) });
|
|
14711
15173
|
}
|
|
14712
15174
|
|
|
15175
|
+
var __defProp = Object.defineProperty;
|
|
15176
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
15177
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
15178
|
+
var _a;
|
|
15179
|
+
const INTERNAL_DATA = Symbol("ScopedStore.data");
|
|
15180
|
+
_a = INTERNAL_DATA;
|
|
15181
|
+
const _ScopedStore = class _ScopedStore {
|
|
15182
|
+
constructor(data) {
|
|
15183
|
+
__publicField(this, _a);
|
|
15184
|
+
this[INTERNAL_DATA] = data;
|
|
15185
|
+
return new Proxy(this, {
|
|
15186
|
+
get(target, prop, receiver) {
|
|
15187
|
+
if (typeof prop === "string") {
|
|
15188
|
+
if (prop === "scope" || prop === "has" || prop === "keys") {
|
|
15189
|
+
return Reflect.get(target, prop, receiver);
|
|
15190
|
+
}
|
|
15191
|
+
return target[INTERNAL_DATA][prop];
|
|
15192
|
+
}
|
|
15193
|
+
return Reflect.get(target, prop, receiver);
|
|
15194
|
+
},
|
|
15195
|
+
has(target, prop) {
|
|
15196
|
+
return typeof prop === "string" ? prop in target[INTERNAL_DATA] : Reflect.has(target, prop);
|
|
15197
|
+
},
|
|
15198
|
+
ownKeys(target) {
|
|
15199
|
+
return Reflect.ownKeys(target[INTERNAL_DATA]);
|
|
15200
|
+
},
|
|
15201
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
15202
|
+
if (typeof prop === "string" && prop in target[INTERNAL_DATA]) {
|
|
15203
|
+
return {
|
|
15204
|
+
configurable: true,
|
|
15205
|
+
enumerable: true,
|
|
15206
|
+
value: target[INTERNAL_DATA][prop]
|
|
15207
|
+
};
|
|
15208
|
+
}
|
|
15209
|
+
return void 0;
|
|
15210
|
+
}
|
|
15211
|
+
});
|
|
15212
|
+
}
|
|
15213
|
+
/**
|
|
15214
|
+
* Access a nested scope by key.
|
|
15215
|
+
* If the key doesn't exist or isn't a scope object, returns an empty ScopedStore.
|
|
15216
|
+
*/
|
|
15217
|
+
scope(key) {
|
|
15218
|
+
const data = this[INTERNAL_DATA][key];
|
|
15219
|
+
return new _ScopedStore(
|
|
15220
|
+
data && typeof data === "object" ? data : {}
|
|
15221
|
+
);
|
|
15222
|
+
}
|
|
15223
|
+
/**
|
|
15224
|
+
* Check if a key exists in the store.
|
|
15225
|
+
*/
|
|
15226
|
+
has(key) {
|
|
15227
|
+
return key in this[INTERNAL_DATA];
|
|
15228
|
+
}
|
|
15229
|
+
/**
|
|
15230
|
+
* Get all keys in the store.
|
|
15231
|
+
*/
|
|
15232
|
+
keys() {
|
|
15233
|
+
return Object.keys(this[INTERNAL_DATA]);
|
|
15234
|
+
}
|
|
15235
|
+
};
|
|
15236
|
+
let ScopedStore = _ScopedStore;
|
|
15237
|
+
function createScopedStore(data) {
|
|
15238
|
+
return new ScopedStore(data);
|
|
15239
|
+
}
|
|
15240
|
+
|
|
14713
15241
|
function addTexture(set, key, value) {
|
|
14714
15242
|
set((state) => {
|
|
14715
15243
|
const newMap = new Map(state.textures);
|
|
@@ -14788,21 +15316,87 @@ function useCompareMemoize(value, deep) {
|
|
|
14788
15316
|
const isUniformNode$1 = (value) => value !== null && typeof value === "object" && "value" in value && "uuid" in value;
|
|
14789
15317
|
function useUniforms(creatorOrScope, scope) {
|
|
14790
15318
|
const store = useStore();
|
|
15319
|
+
const removeUniforms2 = useCallback(
|
|
15320
|
+
(names, targetScope) => {
|
|
15321
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
15322
|
+
store.setState((state) => {
|
|
15323
|
+
if (targetScope) {
|
|
15324
|
+
const currentScope = { ...state.uniforms[targetScope] };
|
|
15325
|
+
for (const name of nameArray) delete currentScope[name];
|
|
15326
|
+
return { uniforms: { ...state.uniforms, [targetScope]: currentScope } };
|
|
15327
|
+
}
|
|
15328
|
+
const uniforms2 = { ...state.uniforms };
|
|
15329
|
+
for (const name of nameArray) if (isUniformNode$1(uniforms2[name])) delete uniforms2[name];
|
|
15330
|
+
return { uniforms: uniforms2 };
|
|
15331
|
+
});
|
|
15332
|
+
},
|
|
15333
|
+
[store]
|
|
15334
|
+
);
|
|
15335
|
+
const clearUniforms = useCallback(
|
|
15336
|
+
(targetScope) => {
|
|
15337
|
+
store.setState((state) => {
|
|
15338
|
+
if (targetScope && targetScope !== "root") {
|
|
15339
|
+
const { [targetScope]: _, ...rest } = state.uniforms;
|
|
15340
|
+
return { uniforms: rest };
|
|
15341
|
+
}
|
|
15342
|
+
if (targetScope === "root") {
|
|
15343
|
+
const uniforms2 = {};
|
|
15344
|
+
for (const [key, value] of Object.entries(state.uniforms)) {
|
|
15345
|
+
if (!isUniformNode$1(value)) uniforms2[key] = value;
|
|
15346
|
+
}
|
|
15347
|
+
return { uniforms: uniforms2 };
|
|
15348
|
+
}
|
|
15349
|
+
return { uniforms: {} };
|
|
15350
|
+
});
|
|
15351
|
+
},
|
|
15352
|
+
[store]
|
|
15353
|
+
);
|
|
15354
|
+
const rebuildUniforms = useCallback(
|
|
15355
|
+
(targetScope) => {
|
|
15356
|
+
store.setState((state) => {
|
|
15357
|
+
let newUniforms = state.uniforms;
|
|
15358
|
+
if (targetScope && targetScope !== "root") {
|
|
15359
|
+
const { [targetScope]: _, ...rest } = state.uniforms;
|
|
15360
|
+
newUniforms = rest;
|
|
15361
|
+
} else if (targetScope === "root") {
|
|
15362
|
+
newUniforms = {};
|
|
15363
|
+
for (const [key, value] of Object.entries(state.uniforms)) {
|
|
15364
|
+
if (!isUniformNode$1(value)) newUniforms[key] = value;
|
|
15365
|
+
}
|
|
15366
|
+
} else {
|
|
15367
|
+
newUniforms = {};
|
|
15368
|
+
}
|
|
15369
|
+
return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
|
|
15370
|
+
});
|
|
15371
|
+
},
|
|
15372
|
+
[store]
|
|
15373
|
+
);
|
|
14791
15374
|
const inputForMemoization = useMemo(() => {
|
|
14792
|
-
|
|
15375
|
+
if (is.fun(creatorOrScope)) {
|
|
15376
|
+
const state = store.getState();
|
|
15377
|
+
const wrappedState = {
|
|
15378
|
+
...state,
|
|
15379
|
+
uniforms: createScopedStore(state.uniforms),
|
|
15380
|
+
nodes: createScopedStore(state.nodes)
|
|
15381
|
+
};
|
|
15382
|
+
return creatorOrScope(wrappedState);
|
|
15383
|
+
}
|
|
15384
|
+
return creatorOrScope;
|
|
14793
15385
|
}, [creatorOrScope, store]);
|
|
14794
15386
|
const memoizedInput = useCompareMemoize(inputForMemoization);
|
|
14795
|
-
|
|
14796
|
-
|
|
14797
|
-
|
|
15387
|
+
const isReader = memoizedInput === void 0 || typeof memoizedInput === "string";
|
|
15388
|
+
const storeUniforms = useThree((s) => s.uniforms);
|
|
15389
|
+
const uniforms = useMemo(() => {
|
|
14798
15390
|
if (memoizedInput === void 0) {
|
|
14799
|
-
return
|
|
15391
|
+
return storeUniforms;
|
|
14800
15392
|
}
|
|
14801
15393
|
if (typeof memoizedInput === "string") {
|
|
14802
|
-
const scopeData =
|
|
15394
|
+
const scopeData = storeUniforms[memoizedInput];
|
|
14803
15395
|
if (scopeData && !isUniformNode$1(scopeData)) return scopeData;
|
|
14804
15396
|
return {};
|
|
14805
15397
|
}
|
|
15398
|
+
const state = store.getState();
|
|
15399
|
+
const set = store.setState;
|
|
14806
15400
|
if (typeof memoizedInput !== "object" || memoizedInput === null) {
|
|
14807
15401
|
throw new Error("Invalid uniform input");
|
|
14808
15402
|
}
|
|
@@ -14838,44 +15432,49 @@ function useUniforms(creatorOrScope, scope) {
|
|
|
14838
15432
|
set((s) => ({
|
|
14839
15433
|
uniforms: {
|
|
14840
15434
|
...s.uniforms,
|
|
14841
|
-
[scope]: {
|
|
14842
|
-
...s.uniforms[scope],
|
|
14843
|
-
...result
|
|
14844
|
-
}
|
|
15435
|
+
[scope]: { ...s.uniforms[scope], ...result }
|
|
14845
15436
|
}
|
|
14846
15437
|
}));
|
|
14847
15438
|
} else {
|
|
14848
|
-
set((s) => ({
|
|
14849
|
-
uniforms: {
|
|
14850
|
-
...s.uniforms,
|
|
14851
|
-
...result
|
|
14852
|
-
}
|
|
14853
|
-
}));
|
|
15439
|
+
set((s) => ({ uniforms: { ...s.uniforms, ...result } }));
|
|
14854
15440
|
}
|
|
14855
15441
|
}
|
|
14856
15442
|
return result;
|
|
14857
|
-
}, [
|
|
15443
|
+
}, [
|
|
15444
|
+
store,
|
|
15445
|
+
memoizedInput,
|
|
15446
|
+
scope,
|
|
15447
|
+
// Only include storeUniforms in deps for reader modes to enable reactivity
|
|
15448
|
+
isReader ? storeUniforms : null
|
|
15449
|
+
]);
|
|
15450
|
+
return { ...uniforms, removeUniforms: removeUniforms2, clearUniforms, rebuildUniforms };
|
|
15451
|
+
}
|
|
15452
|
+
function rebuildAllUniforms(store, scope) {
|
|
15453
|
+
store.setState((state) => {
|
|
15454
|
+
let newUniforms = state.uniforms;
|
|
15455
|
+
if (scope && scope !== "root") {
|
|
15456
|
+
const { [scope]: _, ...rest } = state.uniforms;
|
|
15457
|
+
newUniforms = rest;
|
|
15458
|
+
} else if (scope === "root") {
|
|
15459
|
+
newUniforms = {};
|
|
15460
|
+
for (const [key, value] of Object.entries(state.uniforms)) {
|
|
15461
|
+
if (!isUniformNode$1(value)) newUniforms[key] = value;
|
|
15462
|
+
}
|
|
15463
|
+
} else {
|
|
15464
|
+
newUniforms = {};
|
|
15465
|
+
}
|
|
15466
|
+
return { uniforms: newUniforms, _hmrVersion: state._hmrVersion + 1 };
|
|
15467
|
+
});
|
|
14858
15468
|
}
|
|
14859
15469
|
function removeUniforms(set, names, scope) {
|
|
14860
15470
|
set((state) => {
|
|
14861
15471
|
if (scope) {
|
|
14862
15472
|
const currentScope = { ...state.uniforms[scope] };
|
|
14863
|
-
for (const name of names)
|
|
14864
|
-
|
|
14865
|
-
}
|
|
14866
|
-
return {
|
|
14867
|
-
uniforms: {
|
|
14868
|
-
...state.uniforms,
|
|
14869
|
-
[scope]: currentScope
|
|
14870
|
-
}
|
|
14871
|
-
};
|
|
15473
|
+
for (const name of names) delete currentScope[name];
|
|
15474
|
+
return { uniforms: { ...state.uniforms, [scope]: currentScope } };
|
|
14872
15475
|
}
|
|
14873
15476
|
const uniforms = { ...state.uniforms };
|
|
14874
|
-
for (const name of names)
|
|
14875
|
-
if (isUniformNode$1(uniforms[name])) {
|
|
14876
|
-
delete uniforms[name];
|
|
14877
|
-
}
|
|
14878
|
-
}
|
|
15477
|
+
for (const name of names) if (isUniformNode$1(uniforms[name])) delete uniforms[name];
|
|
14879
15478
|
return { uniforms };
|
|
14880
15479
|
});
|
|
14881
15480
|
}
|
|
@@ -14889,9 +15488,7 @@ function clearRootUniforms(set) {
|
|
|
14889
15488
|
set((state) => {
|
|
14890
15489
|
const uniforms = {};
|
|
14891
15490
|
for (const [key, value] of Object.entries(state.uniforms)) {
|
|
14892
|
-
if (!isUniformNode$1(value))
|
|
14893
|
-
uniforms[key] = value;
|
|
14894
|
-
}
|
|
15491
|
+
if (!isUniformNode$1(value)) uniforms[key] = value;
|
|
14895
15492
|
}
|
|
14896
15493
|
return { uniforms };
|
|
14897
15494
|
});
|
|
@@ -14966,21 +15563,82 @@ function useUniform(name, value) {
|
|
|
14966
15563
|
const isTSLNode = (value) => value !== null && typeof value === "object" && ("uuid" in value || "nodeType" in value);
|
|
14967
15564
|
function useNodes(creatorOrScope, scope) {
|
|
14968
15565
|
const store = useStore();
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
|
|
15566
|
+
const removeNodes2 = useCallback(
|
|
15567
|
+
(names, targetScope) => {
|
|
15568
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
15569
|
+
store.setState((state) => {
|
|
15570
|
+
if (targetScope) {
|
|
15571
|
+
const currentScope = { ...state.nodes[targetScope] };
|
|
15572
|
+
for (const name of nameArray) delete currentScope[name];
|
|
15573
|
+
return { nodes: { ...state.nodes, [targetScope]: currentScope } };
|
|
15574
|
+
}
|
|
15575
|
+
const nodes2 = { ...state.nodes };
|
|
15576
|
+
for (const name of nameArray) if (isTSLNode(nodes2[name])) delete nodes2[name];
|
|
15577
|
+
return { nodes: nodes2 };
|
|
15578
|
+
});
|
|
15579
|
+
},
|
|
15580
|
+
[store]
|
|
15581
|
+
);
|
|
15582
|
+
const clearNodes = useCallback(
|
|
15583
|
+
(targetScope) => {
|
|
15584
|
+
store.setState((state) => {
|
|
15585
|
+
if (targetScope && targetScope !== "root") {
|
|
15586
|
+
const { [targetScope]: _, ...rest } = state.nodes;
|
|
15587
|
+
return { nodes: rest };
|
|
15588
|
+
}
|
|
15589
|
+
if (targetScope === "root") {
|
|
15590
|
+
const nodes2 = {};
|
|
15591
|
+
for (const [key, value] of Object.entries(state.nodes)) {
|
|
15592
|
+
if (!isTSLNode(value)) nodes2[key] = value;
|
|
15593
|
+
}
|
|
15594
|
+
return { nodes: nodes2 };
|
|
15595
|
+
}
|
|
15596
|
+
return { nodes: {} };
|
|
15597
|
+
});
|
|
15598
|
+
},
|
|
15599
|
+
[store]
|
|
15600
|
+
);
|
|
15601
|
+
const rebuildNodes = useCallback(
|
|
15602
|
+
(targetScope) => {
|
|
15603
|
+
store.setState((state) => {
|
|
15604
|
+
let newNodes = state.nodes;
|
|
15605
|
+
if (targetScope && targetScope !== "root") {
|
|
15606
|
+
const { [targetScope]: _, ...rest } = state.nodes;
|
|
15607
|
+
newNodes = rest;
|
|
15608
|
+
} else if (targetScope === "root") {
|
|
15609
|
+
newNodes = {};
|
|
15610
|
+
for (const [key, value] of Object.entries(state.nodes)) {
|
|
15611
|
+
if (!isTSLNode(value)) newNodes[key] = value;
|
|
15612
|
+
}
|
|
15613
|
+
} else {
|
|
15614
|
+
newNodes = {};
|
|
15615
|
+
}
|
|
15616
|
+
return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
|
|
15617
|
+
});
|
|
15618
|
+
},
|
|
15619
|
+
[store]
|
|
15620
|
+
);
|
|
15621
|
+
const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
|
|
15622
|
+
const storeNodes = useThree((s) => s.nodes);
|
|
15623
|
+
const hmrVersion = useThree((s) => s._hmrVersion);
|
|
15624
|
+
const nodes = useMemo(() => {
|
|
14972
15625
|
if (creatorOrScope === void 0) {
|
|
14973
|
-
return
|
|
15626
|
+
return storeNodes;
|
|
14974
15627
|
}
|
|
14975
15628
|
if (typeof creatorOrScope === "string") {
|
|
14976
|
-
const scopeData =
|
|
14977
|
-
if (scopeData && !isTSLNode(scopeData))
|
|
14978
|
-
return scopeData;
|
|
14979
|
-
}
|
|
15629
|
+
const scopeData = storeNodes[creatorOrScope];
|
|
15630
|
+
if (scopeData && !isTSLNode(scopeData)) return scopeData;
|
|
14980
15631
|
return {};
|
|
14981
15632
|
}
|
|
15633
|
+
const state = store.getState();
|
|
15634
|
+
const set = store.setState;
|
|
14982
15635
|
const creator = creatorOrScope;
|
|
14983
|
-
const
|
|
15636
|
+
const wrappedState = {
|
|
15637
|
+
...state,
|
|
15638
|
+
uniforms: createScopedStore(state.uniforms),
|
|
15639
|
+
nodes: createScopedStore(state.nodes)
|
|
15640
|
+
};
|
|
15641
|
+
const created = creator(wrappedState);
|
|
14984
15642
|
const result = {};
|
|
14985
15643
|
let hasNewNodes = false;
|
|
14986
15644
|
if (scope) {
|
|
@@ -14989,9 +15647,7 @@ function useNodes(creatorOrScope, scope) {
|
|
|
14989
15647
|
if (currentScope[name]) {
|
|
14990
15648
|
result[name] = currentScope[name];
|
|
14991
15649
|
} else {
|
|
14992
|
-
if (typeof node.label === "function") {
|
|
14993
|
-
node.setName(`${scope}.${name}`);
|
|
14994
|
-
}
|
|
15650
|
+
if (typeof node.label === "function") node.setName(`${scope}.${name}`);
|
|
14995
15651
|
result[name] = node;
|
|
14996
15652
|
hasNewNodes = true;
|
|
14997
15653
|
}
|
|
@@ -15000,10 +15656,7 @@ function useNodes(creatorOrScope, scope) {
|
|
|
15000
15656
|
set((s) => ({
|
|
15001
15657
|
nodes: {
|
|
15002
15658
|
...s.nodes,
|
|
15003
|
-
[scope]: {
|
|
15004
|
-
...s.nodes[scope],
|
|
15005
|
-
...result
|
|
15006
|
-
}
|
|
15659
|
+
[scope]: { ...s.nodes[scope], ...result }
|
|
15007
15660
|
}
|
|
15008
15661
|
}));
|
|
15009
15662
|
}
|
|
@@ -15014,44 +15667,52 @@ function useNodes(creatorOrScope, scope) {
|
|
|
15014
15667
|
if (existing && isTSLNode(existing)) {
|
|
15015
15668
|
result[name] = existing;
|
|
15016
15669
|
} else {
|
|
15017
|
-
if (typeof node.label === "function")
|
|
15018
|
-
node.setName(name);
|
|
15019
|
-
}
|
|
15670
|
+
if (typeof node.label === "function") node.setName(name);
|
|
15020
15671
|
result[name] = node;
|
|
15021
15672
|
hasNewNodes = true;
|
|
15022
15673
|
}
|
|
15023
15674
|
}
|
|
15024
15675
|
if (hasNewNodes) {
|
|
15025
|
-
set((s) => ({
|
|
15026
|
-
nodes: {
|
|
15027
|
-
...s.nodes,
|
|
15028
|
-
...result
|
|
15029
|
-
}
|
|
15030
|
-
}));
|
|
15676
|
+
set((s) => ({ nodes: { ...s.nodes, ...result } }));
|
|
15031
15677
|
}
|
|
15032
15678
|
return result;
|
|
15033
|
-
}, [
|
|
15679
|
+
}, [
|
|
15680
|
+
store,
|
|
15681
|
+
typeof creatorOrScope === "string" ? creatorOrScope : scope,
|
|
15682
|
+
// Only include storeNodes in deps for reader modes to enable reactivity
|
|
15683
|
+
// Creator mode intentionally excludes it to avoid re-running creator on unrelated changes
|
|
15684
|
+
isReader ? storeNodes : null,
|
|
15685
|
+
// Include hmrVersion for creator modes to allow rebuildNodes() to bust the cache
|
|
15686
|
+
isReader ? null : hmrVersion
|
|
15687
|
+
]);
|
|
15688
|
+
return { ...nodes, removeNodes: removeNodes2, clearNodes, rebuildNodes };
|
|
15689
|
+
}
|
|
15690
|
+
function rebuildAllNodes(store, scope) {
|
|
15691
|
+
store.setState((state) => {
|
|
15692
|
+
let newNodes = state.nodes;
|
|
15693
|
+
if (scope && scope !== "root") {
|
|
15694
|
+
const { [scope]: _, ...rest } = state.nodes;
|
|
15695
|
+
newNodes = rest;
|
|
15696
|
+
} else if (scope === "root") {
|
|
15697
|
+
newNodes = {};
|
|
15698
|
+
for (const [key, value] of Object.entries(state.nodes)) {
|
|
15699
|
+
if (!isTSLNode(value)) newNodes[key] = value;
|
|
15700
|
+
}
|
|
15701
|
+
} else {
|
|
15702
|
+
newNodes = {};
|
|
15703
|
+
}
|
|
15704
|
+
return { nodes: newNodes, _hmrVersion: state._hmrVersion + 1 };
|
|
15705
|
+
});
|
|
15034
15706
|
}
|
|
15035
15707
|
function removeNodes(set, names, scope) {
|
|
15036
15708
|
set((state) => {
|
|
15037
15709
|
if (scope) {
|
|
15038
15710
|
const currentScope = { ...state.nodes[scope] };
|
|
15039
|
-
for (const name of names)
|
|
15040
|
-
|
|
15041
|
-
}
|
|
15042
|
-
return {
|
|
15043
|
-
nodes: {
|
|
15044
|
-
...state.nodes,
|
|
15045
|
-
[scope]: currentScope
|
|
15046
|
-
}
|
|
15047
|
-
};
|
|
15711
|
+
for (const name of names) delete currentScope[name];
|
|
15712
|
+
return { nodes: { ...state.nodes, [scope]: currentScope } };
|
|
15048
15713
|
}
|
|
15049
15714
|
const nodes = { ...state.nodes };
|
|
15050
|
-
for (const name of names)
|
|
15051
|
-
if (isTSLNode(nodes[name])) {
|
|
15052
|
-
delete nodes[name];
|
|
15053
|
-
}
|
|
15054
|
-
}
|
|
15715
|
+
for (const name of names) if (isTSLNode(nodes[name])) delete nodes[name];
|
|
15055
15716
|
return { nodes };
|
|
15056
15717
|
});
|
|
15057
15718
|
}
|
|
@@ -15065,9 +15726,7 @@ function clearRootNodes(set) {
|
|
|
15065
15726
|
set((state) => {
|
|
15066
15727
|
const nodes = {};
|
|
15067
15728
|
for (const [key, value] of Object.entries(state.nodes)) {
|
|
15068
|
-
if (!isTSLNode(value))
|
|
15069
|
-
nodes[key] = value;
|
|
15070
|
-
}
|
|
15729
|
+
if (!isTSLNode(value)) nodes[key] = value;
|
|
15071
15730
|
}
|
|
15072
15731
|
return { nodes };
|
|
15073
15732
|
});
|
|
@@ -15079,7 +15738,12 @@ function useLocalNodes(creator) {
|
|
|
15079
15738
|
const textures = useThree((s) => s.textures);
|
|
15080
15739
|
return useMemo(() => {
|
|
15081
15740
|
const state = store.getState();
|
|
15082
|
-
|
|
15741
|
+
const wrappedState = {
|
|
15742
|
+
...state,
|
|
15743
|
+
uniforms: createScopedStore(state.uniforms),
|
|
15744
|
+
nodes: createScopedStore(state.nodes)
|
|
15745
|
+
};
|
|
15746
|
+
return creator(wrappedState);
|
|
15083
15747
|
}, [store, creator, uniforms, nodes, textures]);
|
|
15084
15748
|
}
|
|
15085
15749
|
|
|
@@ -15093,6 +15757,10 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
15093
15757
|
mainCBRef.current = mainCB;
|
|
15094
15758
|
setupCBRef.current = setupCB;
|
|
15095
15759
|
const [rebuildVersion, setRebuildVersion] = useState(0);
|
|
15760
|
+
useEffect(() => {
|
|
15761
|
+
callbacksRanRef.current = false;
|
|
15762
|
+
scenePassCacheRef.current = null;
|
|
15763
|
+
}, []);
|
|
15096
15764
|
const clearPasses = useCallback(() => {
|
|
15097
15765
|
store.setState({ passes: {} });
|
|
15098
15766
|
}, [store]);
|
|
@@ -15174,4 +15842,4 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
15174
15842
|
|
|
15175
15843
|
extend(THREE);
|
|
15176
15844
|
|
|
15177
|
-
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, useBridge, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, usePostProcessing, useStore, useTexture, useTextures, useThree, useUniform, useUniforms };
|
|
15845
|
+
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, createScopedStore, 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, rebuildAllNodes, rebuildAllUniforms, 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 };
|