@react-three/fiber 10.0.0-canary.b0fafc8 → 10.0.0-canary.c3fa45d
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 +363 -91
- package/dist/index.d.cts +156 -27
- package/dist/index.d.mts +156 -27
- package/dist/index.d.ts +156 -27
- package/dist/index.mjs +364 -92
- package/dist/legacy.cjs +357 -91
- package/dist/legacy.d.cts +156 -27
- package/dist/legacy.d.mts +156 -27
- package/dist/legacy.d.ts +156 -27
- package/dist/legacy.mjs +358 -92
- package/dist/webgpu/index.cjs +738 -102
- package/dist/webgpu/index.d.cts +241 -40
- package/dist/webgpu/index.d.mts +241 -40
- package/dist/webgpu/index.d.ts +241 -40
- package/dist/webgpu/index.mjs +735 -103
- package/package.json +1 -1
package/dist/webgpu/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as webgpu 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,
|
|
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, PCFShadowMap, VSMShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGPURenderer, Vector4, PostProcessing } from 'three/webgpu';
|
|
3
3
|
import { Inspector } from 'three/addons/inspector/Inspector.js';
|
|
4
4
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
5
5
|
import * as React from 'react';
|
|
@@ -149,7 +149,7 @@ function useEnvironment({
|
|
|
149
149
|
useLoader$1.clear(loader, multiFile ? [files] : files);
|
|
150
150
|
}
|
|
151
151
|
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
152
|
-
}, [files, renderer.domElement]);
|
|
152
|
+
}, [extension, files, loader, multiFile, renderer.domElement]);
|
|
153
153
|
const loaderResult = useLoader$1(
|
|
154
154
|
loader,
|
|
155
155
|
multiFile ? [files] : files,
|
|
@@ -349,7 +349,22 @@ function EnvironmentPortal({
|
|
|
349
349
|
environmentIntensity,
|
|
350
350
|
environmentRotation
|
|
351
351
|
});
|
|
352
|
-
}, [
|
|
352
|
+
}, [
|
|
353
|
+
children,
|
|
354
|
+
virtualScene,
|
|
355
|
+
fbo.texture,
|
|
356
|
+
scene,
|
|
357
|
+
defaultScene,
|
|
358
|
+
background,
|
|
359
|
+
frames,
|
|
360
|
+
gl,
|
|
361
|
+
blur,
|
|
362
|
+
backgroundBlurriness,
|
|
363
|
+
backgroundIntensity,
|
|
364
|
+
backgroundRotation,
|
|
365
|
+
environmentIntensity,
|
|
366
|
+
environmentRotation
|
|
367
|
+
]);
|
|
353
368
|
let count = 1;
|
|
354
369
|
useFrame$1(() => {
|
|
355
370
|
if (frames === Infinity || count < frames) {
|
|
@@ -985,6 +1000,9 @@ function applyProps(object, props) {
|
|
|
985
1000
|
else target.set(value);
|
|
986
1001
|
} else {
|
|
987
1002
|
root[key] = value;
|
|
1003
|
+
if (key.endsWith("Node") && root.isMaterial) {
|
|
1004
|
+
root.needsUpdate = true;
|
|
1005
|
+
}
|
|
988
1006
|
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
|
|
989
1007
|
root[key].format === RGBAFormat && root[key].type === UnsignedByteType) {
|
|
990
1008
|
root[key].colorSpace = rootState.textureColorSpace;
|
|
@@ -1018,38 +1036,60 @@ function applyProps(object, props) {
|
|
|
1018
1036
|
return object;
|
|
1019
1037
|
}
|
|
1020
1038
|
|
|
1039
|
+
const DEFAULT_POINTER_ID = 0;
|
|
1040
|
+
const XR_POINTER_ID_START = 1e3;
|
|
1041
|
+
function getPointerState(internal, pointerId) {
|
|
1042
|
+
let state = internal.pointerMap.get(pointerId);
|
|
1043
|
+
if (!state) {
|
|
1044
|
+
state = {
|
|
1045
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
1046
|
+
captured: /* @__PURE__ */ new Map(),
|
|
1047
|
+
initialClick: [0, 0],
|
|
1048
|
+
initialHits: []
|
|
1049
|
+
};
|
|
1050
|
+
internal.pointerMap.set(pointerId, state);
|
|
1051
|
+
}
|
|
1052
|
+
return state;
|
|
1053
|
+
}
|
|
1054
|
+
function getPointerId(event) {
|
|
1055
|
+
return "pointerId" in event ? event.pointerId : DEFAULT_POINTER_ID;
|
|
1056
|
+
}
|
|
1021
1057
|
function makeId(event) {
|
|
1022
1058
|
return (event.eventObject || event.object).uuid + "/" + event.index + event.instanceId;
|
|
1023
1059
|
}
|
|
1024
|
-
function releaseInternalPointerCapture(
|
|
1025
|
-
const
|
|
1060
|
+
function releaseInternalPointerCapture(internal, obj, pointerId) {
|
|
1061
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1062
|
+
if (!pointerState) return;
|
|
1063
|
+
const captureData = pointerState.captured.get(obj);
|
|
1026
1064
|
if (captureData) {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
capturedMap.delete(pointerId);
|
|
1030
|
-
captureData.target.releasePointerCapture(pointerId);
|
|
1031
|
-
}
|
|
1065
|
+
pointerState.captured.delete(obj);
|
|
1066
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
1032
1067
|
}
|
|
1033
1068
|
}
|
|
1034
1069
|
function removeInteractivity(store, object) {
|
|
1035
1070
|
const { internal } = store.getState();
|
|
1036
1071
|
internal.interaction = internal.interaction.filter((o) => o !== object);
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1072
|
+
for (const [pointerId, pointerState] of internal.pointerMap) {
|
|
1073
|
+
pointerState.initialHits = pointerState.initialHits.filter((o) => o !== object);
|
|
1074
|
+
pointerState.hovered.forEach((value, key) => {
|
|
1075
|
+
if (value.eventObject === object || value.object === object) {
|
|
1076
|
+
pointerState.hovered.delete(key);
|
|
1077
|
+
}
|
|
1078
|
+
});
|
|
1079
|
+
if (pointerState.captured.has(object)) {
|
|
1080
|
+
releaseInternalPointerCapture(internal, object, pointerId);
|
|
1041
1081
|
}
|
|
1042
|
-
}
|
|
1043
|
-
internal.capturedMap.forEach((captures, pointerId) => {
|
|
1044
|
-
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
1045
|
-
});
|
|
1082
|
+
}
|
|
1046
1083
|
unregisterVisibility(store, object);
|
|
1047
1084
|
}
|
|
1048
1085
|
function createEvents(store) {
|
|
1049
|
-
function calculateDistance(event) {
|
|
1086
|
+
function calculateDistance(event, pointerId) {
|
|
1050
1087
|
const { internal } = store.getState();
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1088
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1089
|
+
if (!pointerState) return 0;
|
|
1090
|
+
const [initialX, initialY] = pointerState.initialClick;
|
|
1091
|
+
const dx = event.offsetX - initialX;
|
|
1092
|
+
const dy = event.offsetY - initialY;
|
|
1053
1093
|
return Math.round(Math.sqrt(dx * dx + dy * dy));
|
|
1054
1094
|
}
|
|
1055
1095
|
function filterPointerEvents(objects) {
|
|
@@ -1085,6 +1125,15 @@ function createEvents(store) {
|
|
|
1085
1125
|
return state2.raycaster.camera ? state2.raycaster.intersectObject(obj, true) : [];
|
|
1086
1126
|
}
|
|
1087
1127
|
let hits = eventsObjects.flatMap(handleRaycast).sort((a, b) => {
|
|
1128
|
+
const aInteractivePriority = a.object.userData?.interactivePriority;
|
|
1129
|
+
const bInteractivePriority = b.object.userData?.interactivePriority;
|
|
1130
|
+
if (aInteractivePriority !== void 0 || bInteractivePriority !== void 0) {
|
|
1131
|
+
if (aInteractivePriority !== void 0 && bInteractivePriority === void 0) return -1;
|
|
1132
|
+
if (bInteractivePriority !== void 0 && aInteractivePriority === void 0) return 1;
|
|
1133
|
+
if (aInteractivePriority !== bInteractivePriority) {
|
|
1134
|
+
return (bInteractivePriority ?? 0) - (aInteractivePriority ?? 0);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1088
1137
|
const aState = getRootState(a.object);
|
|
1089
1138
|
const bState = getRootState(b.object);
|
|
1090
1139
|
const aPriority = aState?.events?.priority ?? 1;
|
|
@@ -1106,9 +1155,13 @@ function createEvents(store) {
|
|
|
1106
1155
|
eventObject = eventObject.parent;
|
|
1107
1156
|
}
|
|
1108
1157
|
}
|
|
1109
|
-
if ("pointerId" in event
|
|
1110
|
-
|
|
1111
|
-
|
|
1158
|
+
if ("pointerId" in event) {
|
|
1159
|
+
const pointerId = event.pointerId;
|
|
1160
|
+
const pointerState = state.internal.pointerMap.get(pointerId);
|
|
1161
|
+
if (pointerState?.captured.size) {
|
|
1162
|
+
for (const captureData of pointerState.captured.values()) {
|
|
1163
|
+
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
1164
|
+
}
|
|
1112
1165
|
}
|
|
1113
1166
|
}
|
|
1114
1167
|
return intersections;
|
|
@@ -1121,27 +1174,25 @@ function createEvents(store) {
|
|
|
1121
1174
|
if (state) {
|
|
1122
1175
|
const { raycaster, pointer, camera, internal } = state;
|
|
1123
1176
|
const unprojectedPoint = new Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
1124
|
-
const hasPointerCapture = (id) =>
|
|
1177
|
+
const hasPointerCapture = (id) => {
|
|
1178
|
+
const pointerState = internal.pointerMap.get(id);
|
|
1179
|
+
return pointerState?.captured.has(hit.eventObject) ?? false;
|
|
1180
|
+
};
|
|
1125
1181
|
const setPointerCapture = (id) => {
|
|
1126
1182
|
const captureData = { intersection: hit, target: event.target };
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
} else {
|
|
1130
|
-
internal.capturedMap.set(id, /* @__PURE__ */ new Map([[hit.eventObject, captureData]]));
|
|
1131
|
-
}
|
|
1183
|
+
const pointerState = getPointerState(internal, id);
|
|
1184
|
+
pointerState.captured.set(hit.eventObject, captureData);
|
|
1132
1185
|
event.target.setPointerCapture(id);
|
|
1133
1186
|
};
|
|
1134
1187
|
const releasePointerCapture = (id) => {
|
|
1135
|
-
|
|
1136
|
-
if (captures) {
|
|
1137
|
-
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
1138
|
-
}
|
|
1188
|
+
releaseInternalPointerCapture(internal, hit.eventObject, id);
|
|
1139
1189
|
};
|
|
1140
1190
|
const extractEventProps = {};
|
|
1141
1191
|
for (const prop in event) {
|
|
1142
1192
|
const property = event[prop];
|
|
1143
1193
|
if (typeof property !== "function") extractEventProps[prop] = property;
|
|
1144
1194
|
}
|
|
1195
|
+
const eventPointerId = "pointerId" in event ? event.pointerId : void 0;
|
|
1145
1196
|
const raycastEvent = {
|
|
1146
1197
|
...hit,
|
|
1147
1198
|
...extractEventProps,
|
|
@@ -1152,18 +1203,19 @@ function createEvents(store) {
|
|
|
1152
1203
|
unprojectedPoint,
|
|
1153
1204
|
ray: raycaster.ray,
|
|
1154
1205
|
camera,
|
|
1206
|
+
pointerId: eventPointerId,
|
|
1155
1207
|
// Hijack stopPropagation, which just sets a flag
|
|
1156
1208
|
stopPropagation() {
|
|
1157
|
-
const
|
|
1209
|
+
const pointerState = eventPointerId !== void 0 ? internal.pointerMap.get(eventPointerId) : void 0;
|
|
1158
1210
|
if (
|
|
1159
1211
|
// ...if this pointer hasn't been captured
|
|
1160
|
-
!
|
|
1161
|
-
|
|
1212
|
+
!pointerState?.captured.size || // ... or if the hit object is capturing the pointer
|
|
1213
|
+
pointerState.captured.has(hit.eventObject)
|
|
1162
1214
|
) {
|
|
1163
1215
|
raycastEvent.stopped = localState.stopped = true;
|
|
1164
|
-
if (
|
|
1216
|
+
if (pointerState?.hovered.size && Array.from(pointerState.hovered.values()).find((i) => i.eventObject === hit.eventObject)) {
|
|
1165
1217
|
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
1166
|
-
cancelPointer([...higher, hit]);
|
|
1218
|
+
cancelPointer([...higher, hit], eventPointerId);
|
|
1167
1219
|
}
|
|
1168
1220
|
}
|
|
1169
1221
|
},
|
|
@@ -1179,15 +1231,18 @@ function createEvents(store) {
|
|
|
1179
1231
|
}
|
|
1180
1232
|
return intersections;
|
|
1181
1233
|
}
|
|
1182
|
-
function cancelPointer(intersections) {
|
|
1234
|
+
function cancelPointer(intersections, pointerId) {
|
|
1183
1235
|
const { internal } = store.getState();
|
|
1184
|
-
|
|
1236
|
+
const pid = pointerId ?? DEFAULT_POINTER_ID;
|
|
1237
|
+
const pointerState = internal.pointerMap.get(pid);
|
|
1238
|
+
if (!pointerState) return;
|
|
1239
|
+
for (const [hoveredId, hoveredObj] of pointerState.hovered) {
|
|
1185
1240
|
if (!intersections.length || !intersections.find(
|
|
1186
1241
|
(hit) => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId
|
|
1187
1242
|
)) {
|
|
1188
1243
|
const eventObject = hoveredObj.eventObject;
|
|
1189
1244
|
const instance = eventObject.__r3f;
|
|
1190
|
-
|
|
1245
|
+
pointerState.hovered.delete(hoveredId);
|
|
1191
1246
|
if (instance?.eventCount) {
|
|
1192
1247
|
const handlers = instance.handlers;
|
|
1193
1248
|
const data = { ...hoveredObj, intersections };
|
|
@@ -1216,41 +1271,118 @@ function createEvents(store) {
|
|
|
1216
1271
|
instance?.handlers.onDropMissed?.(event);
|
|
1217
1272
|
}
|
|
1218
1273
|
}
|
|
1274
|
+
function cleanupPointer(pointerId) {
|
|
1275
|
+
const { internal } = store.getState();
|
|
1276
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1277
|
+
if (pointerState) {
|
|
1278
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1279
|
+
const eventObject = hoveredObj.eventObject;
|
|
1280
|
+
const instance = eventObject.__r3f;
|
|
1281
|
+
if (instance?.eventCount) {
|
|
1282
|
+
const handlers = instance.handlers;
|
|
1283
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1284
|
+
handlers.onPointerOut?.(data);
|
|
1285
|
+
handlers.onPointerLeave?.(data);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
internal.pointerMap.delete(pointerId);
|
|
1289
|
+
}
|
|
1290
|
+
internal.pointerDirty.delete(pointerId);
|
|
1291
|
+
}
|
|
1292
|
+
function processDeferredPointer(event, pointerId) {
|
|
1293
|
+
const state = store.getState();
|
|
1294
|
+
const { internal } = state;
|
|
1295
|
+
if (!state.events.enabled) return;
|
|
1296
|
+
const filter = filterPointerEvents;
|
|
1297
|
+
const hits = intersect(event, filter);
|
|
1298
|
+
cancelPointer(hits, pointerId);
|
|
1299
|
+
function onIntersect(data) {
|
|
1300
|
+
const eventObject = data.eventObject;
|
|
1301
|
+
const instance = eventObject.__r3f;
|
|
1302
|
+
if (!instance?.eventCount) return;
|
|
1303
|
+
const handlers = instance.handlers;
|
|
1304
|
+
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
1305
|
+
const id = makeId(data);
|
|
1306
|
+
const pointerState = getPointerState(internal, pointerId);
|
|
1307
|
+
const hoveredItem = pointerState.hovered.get(id);
|
|
1308
|
+
if (!hoveredItem) {
|
|
1309
|
+
pointerState.hovered.set(id, data);
|
|
1310
|
+
handlers.onPointerOver?.(data);
|
|
1311
|
+
handlers.onPointerEnter?.(data);
|
|
1312
|
+
} else if (hoveredItem.stopped) {
|
|
1313
|
+
data.stopPropagation();
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
handlers.onPointerMove?.(data);
|
|
1317
|
+
}
|
|
1318
|
+
handleIntersects(hits, event, 0, onIntersect);
|
|
1319
|
+
}
|
|
1219
1320
|
function handlePointer(name) {
|
|
1220
1321
|
switch (name) {
|
|
1221
1322
|
case "onPointerLeave":
|
|
1222
|
-
case "onPointerCancel":
|
|
1223
1323
|
case "onDragLeave":
|
|
1224
1324
|
return () => cancelPointer([]);
|
|
1325
|
+
// Global cancel of these events
|
|
1326
|
+
case "onPointerCancel":
|
|
1327
|
+
return (event) => {
|
|
1328
|
+
const pointerId = getPointerId(event);
|
|
1329
|
+
cleanupPointer(pointerId);
|
|
1330
|
+
};
|
|
1225
1331
|
case "onLostPointerCapture":
|
|
1226
1332
|
return (event) => {
|
|
1227
1333
|
const { internal } = store.getState();
|
|
1228
|
-
|
|
1334
|
+
const pointerId = getPointerId(event);
|
|
1335
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1336
|
+
if (pointerState?.captured.size) {
|
|
1229
1337
|
requestAnimationFrame(() => {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1338
|
+
const pointerState2 = internal.pointerMap.get(pointerId);
|
|
1339
|
+
if (pointerState2?.captured.size) {
|
|
1340
|
+
pointerState2.captured.clear();
|
|
1233
1341
|
}
|
|
1342
|
+
cancelPointer([], pointerId);
|
|
1234
1343
|
});
|
|
1235
1344
|
}
|
|
1236
1345
|
};
|
|
1237
1346
|
}
|
|
1238
1347
|
return function handleEvent(event) {
|
|
1239
1348
|
const state = store.getState();
|
|
1240
|
-
const { onPointerMissed, onDragOverMissed, onDropMissed, internal } = state;
|
|
1349
|
+
const { onPointerMissed, onDragOverMissed, onDropMissed, internal, events } = state;
|
|
1350
|
+
const pointerId = getPointerId(event);
|
|
1241
1351
|
internal.lastEvent.current = event;
|
|
1242
|
-
if (!
|
|
1352
|
+
if (!events.enabled) return;
|
|
1243
1353
|
const isPointerMove = name === "onPointerMove";
|
|
1244
1354
|
const isDragOver = name === "onDragOver";
|
|
1245
1355
|
const isDrop = name === "onDrop";
|
|
1246
1356
|
const isClickEvent = name === "onClick" || name === "onContextMenu" || name === "onDoubleClick";
|
|
1357
|
+
const isPointerDown = name === "onPointerDown";
|
|
1358
|
+
const isPointerUp = name === "onPointerUp";
|
|
1359
|
+
const isWheel = name === "onWheel";
|
|
1360
|
+
const canDeferRaycasts = events.frameTimedRaycasts && state.frameloop === "always";
|
|
1361
|
+
if (isPointerMove && canDeferRaycasts) {
|
|
1362
|
+
events.compute?.(event, state);
|
|
1363
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
if (isWheel && canDeferRaycasts && !events.alwaysFireOnScroll) {
|
|
1367
|
+
events.compute?.(event, state);
|
|
1368
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
if ((isClickEvent || isPointerDown || isPointerUp) && internal.pointerDirty.has(pointerId)) {
|
|
1372
|
+
const deferredEvent = internal.pointerDirty.get(pointerId);
|
|
1373
|
+
internal.pointerDirty.delete(pointerId);
|
|
1374
|
+
processDeferredPointer(deferredEvent, pointerId);
|
|
1375
|
+
}
|
|
1247
1376
|
const filter = isPointerMove || isDragOver || isDrop ? filterPointerEvents : void 0;
|
|
1248
1377
|
const hits = intersect(event, filter);
|
|
1249
|
-
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
1250
|
-
if (
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1378
|
+
const delta = isClickEvent ? calculateDistance(event, pointerId) : 0;
|
|
1379
|
+
if (isPointerDown) {
|
|
1380
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1381
|
+
pointerState2.initialClick = [event.offsetX, event.offsetY];
|
|
1382
|
+
pointerState2.initialHits = hits.map((hit) => hit.eventObject);
|
|
1383
|
+
}
|
|
1384
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1385
|
+
const initialHits = pointerState?.initialHits ?? [];
|
|
1254
1386
|
if (isClickEvent && !hits.length) {
|
|
1255
1387
|
if (delta <= 2) {
|
|
1256
1388
|
pointerMissed(event, internal.interaction);
|
|
@@ -1265,7 +1397,9 @@ function createEvents(store) {
|
|
|
1265
1397
|
dropMissed(event, internal.interaction);
|
|
1266
1398
|
if (onDropMissed) onDropMissed(event);
|
|
1267
1399
|
}
|
|
1268
|
-
if (isPointerMove || isDragOver)
|
|
1400
|
+
if (isPointerMove || isDragOver) {
|
|
1401
|
+
cancelPointer(hits, pointerId);
|
|
1402
|
+
}
|
|
1269
1403
|
function onIntersect(data) {
|
|
1270
1404
|
const eventObject = data.eventObject;
|
|
1271
1405
|
const instance = eventObject.__r3f;
|
|
@@ -1274,9 +1408,10 @@ function createEvents(store) {
|
|
|
1274
1408
|
if (isPointerMove) {
|
|
1275
1409
|
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
1276
1410
|
const id = makeId(data);
|
|
1277
|
-
const
|
|
1411
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1412
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
1278
1413
|
if (!hoveredItem) {
|
|
1279
|
-
|
|
1414
|
+
pointerState2.hovered.set(id, data);
|
|
1280
1415
|
handlers.onPointerOver?.(data);
|
|
1281
1416
|
handlers.onPointerEnter?.(data);
|
|
1282
1417
|
} else if (hoveredItem.stopped) {
|
|
@@ -1286,9 +1421,10 @@ function createEvents(store) {
|
|
|
1286
1421
|
handlers.onPointerMove?.(data);
|
|
1287
1422
|
} else if (isDragOver) {
|
|
1288
1423
|
const id = makeId(data);
|
|
1289
|
-
const
|
|
1424
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1425
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
1290
1426
|
if (!hoveredItem) {
|
|
1291
|
-
|
|
1427
|
+
pointerState2.hovered.set(id, data);
|
|
1292
1428
|
handlers.onDragOverEnter?.(data);
|
|
1293
1429
|
} else if (hoveredItem.stopped) {
|
|
1294
1430
|
data.stopPropagation();
|
|
@@ -1299,18 +1435,18 @@ function createEvents(store) {
|
|
|
1299
1435
|
} else {
|
|
1300
1436
|
const handler = handlers[name];
|
|
1301
1437
|
if (handler) {
|
|
1302
|
-
if (!isClickEvent ||
|
|
1438
|
+
if (!isClickEvent || initialHits.includes(eventObject)) {
|
|
1303
1439
|
pointerMissed(
|
|
1304
1440
|
event,
|
|
1305
|
-
internal.interaction.filter((object) => !
|
|
1441
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
1306
1442
|
);
|
|
1307
1443
|
handler(data);
|
|
1308
1444
|
}
|
|
1309
1445
|
} else {
|
|
1310
|
-
if (isClickEvent &&
|
|
1446
|
+
if (isClickEvent && initialHits.includes(eventObject)) {
|
|
1311
1447
|
pointerMissed(
|
|
1312
1448
|
event,
|
|
1313
|
-
internal.interaction.filter((object) => !
|
|
1449
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
1314
1450
|
);
|
|
1315
1451
|
}
|
|
1316
1452
|
}
|
|
@@ -1319,7 +1455,15 @@ function createEvents(store) {
|
|
|
1319
1455
|
handleIntersects(hits, event, delta, onIntersect);
|
|
1320
1456
|
};
|
|
1321
1457
|
}
|
|
1322
|
-
|
|
1458
|
+
function flushDeferredPointers() {
|
|
1459
|
+
const { internal, events } = store.getState();
|
|
1460
|
+
if (!events.frameTimedRaycasts) return;
|
|
1461
|
+
for (const [pointerId, event] of internal.pointerDirty) {
|
|
1462
|
+
processDeferredPointer(event, pointerId);
|
|
1463
|
+
}
|
|
1464
|
+
internal.pointerDirty.clear();
|
|
1465
|
+
}
|
|
1466
|
+
return { handlePointer, flushDeferredPointers, processDeferredPointer };
|
|
1323
1467
|
}
|
|
1324
1468
|
const DOM_EVENTS = {
|
|
1325
1469
|
onClick: ["click", false],
|
|
@@ -1338,10 +1482,15 @@ const DOM_EVENTS = {
|
|
|
1338
1482
|
onLostPointerCapture: ["lostpointercapture", true]
|
|
1339
1483
|
};
|
|
1340
1484
|
function createPointerEvents(store) {
|
|
1341
|
-
const { handlePointer } = createEvents(store);
|
|
1485
|
+
const { handlePointer, flushDeferredPointers, processDeferredPointer } = createEvents(store);
|
|
1486
|
+
let nextXRPointerId = XR_POINTER_ID_START;
|
|
1487
|
+
const xrPointers = /* @__PURE__ */ new Map();
|
|
1342
1488
|
return {
|
|
1343
1489
|
priority: 1,
|
|
1344
1490
|
enabled: true,
|
|
1491
|
+
frameTimedRaycasts: true,
|
|
1492
|
+
alwaysFireOnScroll: true,
|
|
1493
|
+
updateOnFrame: false,
|
|
1345
1494
|
compute(event, state) {
|
|
1346
1495
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
1347
1496
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
@@ -1351,11 +1500,33 @@ function createPointerEvents(store) {
|
|
|
1351
1500
|
(acc, key) => ({ ...acc, [key]: handlePointer(key) }),
|
|
1352
1501
|
{}
|
|
1353
1502
|
),
|
|
1354
|
-
update: () => {
|
|
1503
|
+
update: (pointerId) => {
|
|
1355
1504
|
const { events, internal } = store.getState();
|
|
1356
|
-
if (
|
|
1505
|
+
if (!events.handlers) return;
|
|
1506
|
+
if (pointerId !== void 0) {
|
|
1507
|
+
const event = internal.pointerDirty.get(pointerId);
|
|
1508
|
+
if (event) {
|
|
1509
|
+
internal.pointerDirty.delete(pointerId);
|
|
1510
|
+
processDeferredPointer(event, pointerId);
|
|
1511
|
+
} else if (internal.lastEvent?.current) {
|
|
1512
|
+
processDeferredPointer(internal.lastEvent.current, pointerId);
|
|
1513
|
+
}
|
|
1514
|
+
} else {
|
|
1515
|
+
flushDeferredPointers();
|
|
1516
|
+
if (internal.lastEvent?.current) {
|
|
1517
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
},
|
|
1521
|
+
flush: () => {
|
|
1522
|
+
const { events, internal } = store.getState();
|
|
1523
|
+
flushDeferredPointers();
|
|
1524
|
+
if (events.updateOnFrame && internal.lastEvent?.current && events.handlers) {
|
|
1525
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1526
|
+
}
|
|
1357
1527
|
},
|
|
1358
1528
|
connect: (target) => {
|
|
1529
|
+
if (!target) return;
|
|
1359
1530
|
const { set, events } = store.getState();
|
|
1360
1531
|
events.disconnect?.();
|
|
1361
1532
|
set((state) => ({ events: { ...state.events, connected: target } }));
|
|
@@ -1379,6 +1550,32 @@ function createPointerEvents(store) {
|
|
|
1379
1550
|
}
|
|
1380
1551
|
set((state) => ({ events: { ...state.events, connected: void 0 } }));
|
|
1381
1552
|
}
|
|
1553
|
+
},
|
|
1554
|
+
registerPointer: (config) => {
|
|
1555
|
+
const pointerId = nextXRPointerId++;
|
|
1556
|
+
xrPointers.set(pointerId, config);
|
|
1557
|
+
const { internal } = store.getState();
|
|
1558
|
+
getPointerState(internal, pointerId);
|
|
1559
|
+
return pointerId;
|
|
1560
|
+
},
|
|
1561
|
+
unregisterPointer: (pointerId) => {
|
|
1562
|
+
xrPointers.delete(pointerId);
|
|
1563
|
+
const { internal } = store.getState();
|
|
1564
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1565
|
+
if (pointerState) {
|
|
1566
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1567
|
+
const eventObject = hoveredObj.eventObject;
|
|
1568
|
+
const instance = eventObject.__r3f;
|
|
1569
|
+
if (instance?.eventCount) {
|
|
1570
|
+
const handlers = instance.handlers;
|
|
1571
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1572
|
+
handlers.onPointerOut?.(data);
|
|
1573
|
+
handlers.onPointerLeave?.(data);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
internal.pointerMap.delete(pointerId);
|
|
1577
|
+
}
|
|
1578
|
+
internal.pointerDirty.delete(pointerId);
|
|
1382
1579
|
}
|
|
1383
1580
|
};
|
|
1384
1581
|
}
|
|
@@ -1692,7 +1889,7 @@ function shouldRun(job, now) {
|
|
|
1692
1889
|
const minInterval = 1e3 / job.fps;
|
|
1693
1890
|
const lastRun = job.lastRun ?? 0;
|
|
1694
1891
|
const elapsed = now - lastRun;
|
|
1695
|
-
if (elapsed < minInterval) return false;
|
|
1892
|
+
if (elapsed < minInterval - 1) return false;
|
|
1696
1893
|
if (job.drop) {
|
|
1697
1894
|
job.lastRun = now;
|
|
1698
1895
|
} else {
|
|
@@ -2509,7 +2706,14 @@ const createStore = (invalidate, advance) => {
|
|
|
2509
2706
|
frustum: new Frustum(),
|
|
2510
2707
|
autoUpdateFrustum: true,
|
|
2511
2708
|
raycaster: null,
|
|
2512
|
-
events: {
|
|
2709
|
+
events: {
|
|
2710
|
+
priority: 1,
|
|
2711
|
+
enabled: true,
|
|
2712
|
+
connected: false,
|
|
2713
|
+
frameTimedRaycasts: true,
|
|
2714
|
+
alwaysFireOnScroll: true,
|
|
2715
|
+
updateOnFrame: false
|
|
2716
|
+
},
|
|
2513
2717
|
scene: null,
|
|
2514
2718
|
rootScene: null,
|
|
2515
2719
|
xr: null,
|
|
@@ -2600,11 +2804,13 @@ const createStore = (invalidate, advance) => {
|
|
|
2600
2804
|
},
|
|
2601
2805
|
setError: (error) => set(() => ({ error })),
|
|
2602
2806
|
error: null,
|
|
2603
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures,
|
|
2807
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
2604
2808
|
uniforms: {},
|
|
2605
2809
|
nodes: {},
|
|
2810
|
+
buffers: {},
|
|
2811
|
+
gpuStorage: {},
|
|
2606
2812
|
textures: /* @__PURE__ */ new Map(),
|
|
2607
|
-
|
|
2813
|
+
renderPipeline: null,
|
|
2608
2814
|
passes: {},
|
|
2609
2815
|
_hmrVersion: 0,
|
|
2610
2816
|
_sizeImperative: false,
|
|
@@ -2613,12 +2819,16 @@ const createStore = (invalidate, advance) => {
|
|
|
2613
2819
|
internal: {
|
|
2614
2820
|
// Events
|
|
2615
2821
|
interaction: [],
|
|
2616
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
2617
2822
|
subscribers: [],
|
|
2823
|
+
// Per-pointer state (new unified structure)
|
|
2824
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
2825
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
2826
|
+
lastEvent: React.createRef(),
|
|
2827
|
+
// Deprecated but kept for backwards compatibility
|
|
2828
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
2618
2829
|
initialClick: [0, 0],
|
|
2619
2830
|
initialHits: [],
|
|
2620
2831
|
capturedMap: /* @__PURE__ */ new Map(),
|
|
2621
|
-
lastEvent: React.createRef(),
|
|
2622
2832
|
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
2623
2833
|
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
2624
2834
|
// Occlusion system (WebGPU only)
|
|
@@ -2706,14 +2916,16 @@ const createStore = (invalidate, advance) => {
|
|
|
2706
2916
|
oldSize = size;
|
|
2707
2917
|
oldDpr = viewport.dpr;
|
|
2708
2918
|
updateCamera(camera, size);
|
|
2709
|
-
if (canvasTarget) {
|
|
2919
|
+
if (internal.isSecondary && canvasTarget) {
|
|
2710
2920
|
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2711
|
-
|
|
2712
|
-
canvasTarget.setSize(size.width, size.height, updateStyle);
|
|
2921
|
+
canvasTarget.setSize(size.width, size.height, false);
|
|
2713
2922
|
} else {
|
|
2714
2923
|
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
2715
|
-
|
|
2716
|
-
|
|
2924
|
+
actualRenderer.setSize(size.width, size.height, false);
|
|
2925
|
+
if (canvasTarget) {
|
|
2926
|
+
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2927
|
+
canvasTarget.setSize(size.width, size.height, false);
|
|
2928
|
+
}
|
|
2717
2929
|
}
|
|
2718
2930
|
}
|
|
2719
2931
|
if (camera !== oldCamera) {
|
|
@@ -14998,7 +15210,6 @@ function createRoot(canvas) {
|
|
|
14998
15210
|
events,
|
|
14999
15211
|
onCreated: onCreatedCallback,
|
|
15000
15212
|
shadows = false,
|
|
15001
|
-
textureColorSpace = SRGBColorSpace,
|
|
15002
15213
|
orthographic = false,
|
|
15003
15214
|
frameloop = "always",
|
|
15004
15215
|
dpr = [1, 2],
|
|
@@ -15013,6 +15224,7 @@ function createRoot(canvas) {
|
|
|
15013
15224
|
_sizeProps,
|
|
15014
15225
|
forceEven
|
|
15015
15226
|
} = props;
|
|
15227
|
+
const textureColorSpace = is.obj(glConfig) && !is.fun(glConfig) && !isRenderer(glConfig) && glConfig.textureColorSpace || is.obj(rendererConfig) && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && rendererConfig.textureColorSpace || SRGBColorSpace;
|
|
15016
15228
|
const state = store.getState();
|
|
15017
15229
|
const defaultGPUProps = {
|
|
15018
15230
|
canvas,
|
|
@@ -15050,6 +15262,12 @@ function createRoot(canvas) {
|
|
|
15050
15262
|
} else if (!state.internal.actualRenderer) {
|
|
15051
15263
|
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, WebGPURenderer);
|
|
15052
15264
|
if (!renderer.hasInitialized?.()) {
|
|
15265
|
+
const size2 = computeInitialSize(canvas, propsSize);
|
|
15266
|
+
if (size2.width > 0 && size2.height > 0) {
|
|
15267
|
+
const pixelRatio = calculateDpr(dpr);
|
|
15268
|
+
canvas.width = size2.width * pixelRatio;
|
|
15269
|
+
canvas.height = size2.height * pixelRatio;
|
|
15270
|
+
}
|
|
15053
15271
|
await renderer.init();
|
|
15054
15272
|
}
|
|
15055
15273
|
const backend = renderer.backend;
|
|
@@ -15159,7 +15377,7 @@ function createRoot(canvas) {
|
|
|
15159
15377
|
lastConfiguredProps.performance = performance;
|
|
15160
15378
|
}
|
|
15161
15379
|
if (!state.xr) {
|
|
15162
|
-
const handleXRFrame = (timestamp,
|
|
15380
|
+
const handleXRFrame = (timestamp, _frame) => {
|
|
15163
15381
|
const state2 = store.getState();
|
|
15164
15382
|
if (state2.frameloop === "never") return;
|
|
15165
15383
|
advance(timestamp);
|
|
@@ -15195,15 +15413,22 @@ function createRoot(canvas) {
|
|
|
15195
15413
|
const oldType = renderer.shadowMap.type;
|
|
15196
15414
|
renderer.shadowMap.enabled = !!shadows;
|
|
15197
15415
|
if (is.boo(shadows)) {
|
|
15198
|
-
renderer.shadowMap.type =
|
|
15416
|
+
renderer.shadowMap.type = PCFShadowMap;
|
|
15199
15417
|
} else if (is.str(shadows)) {
|
|
15418
|
+
if (shadows === "soft") {
|
|
15419
|
+
notifyDepreciated({
|
|
15420
|
+
heading: 'shadows="soft" is deprecated',
|
|
15421
|
+
body: "Three has depreciated soft and improved basic PCFShadows, we converted for you.",
|
|
15422
|
+
link: "https://github.com/mrdoob/three.js/wiki/Migration-Guide?utm_source=chatgpt.com#181--182"
|
|
15423
|
+
});
|
|
15424
|
+
}
|
|
15200
15425
|
const types = {
|
|
15201
15426
|
basic: BasicShadowMap,
|
|
15202
15427
|
percentage: PCFShadowMap,
|
|
15203
|
-
soft:
|
|
15428
|
+
soft: PCFShadowMap,
|
|
15204
15429
|
variance: VSMShadowMap
|
|
15205
15430
|
};
|
|
15206
|
-
renderer.shadowMap.type = types[shadows] ??
|
|
15431
|
+
renderer.shadowMap.type = types[shadows] ?? PCFShadowMap;
|
|
15207
15432
|
} else if (is.obj(shadows)) {
|
|
15208
15433
|
Object.assign(renderer.shadowMap, shadows);
|
|
15209
15434
|
}
|
|
@@ -15219,13 +15444,24 @@ function createRoot(canvas) {
|
|
|
15219
15444
|
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
15220
15445
|
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
15221
15446
|
}
|
|
15447
|
+
const r3fProps = ["textureColorSpace"];
|
|
15448
|
+
const constructorOnlyProps = ["samples", "antialias", "alpha", "canvas", "powerPreference"];
|
|
15449
|
+
const nonApplyProps = [...r3fProps, ...constructorOnlyProps];
|
|
15222
15450
|
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
15223
|
-
|
|
15451
|
+
const glProps = {};
|
|
15452
|
+
for (const key in glConfig) {
|
|
15453
|
+
if (!nonApplyProps.includes(key)) glProps[key] = glConfig[key];
|
|
15454
|
+
}
|
|
15455
|
+
applyProps(renderer, glProps);
|
|
15224
15456
|
}
|
|
15225
15457
|
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
15226
15458
|
const currentRenderer = state.renderer;
|
|
15227
15459
|
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
15228
|
-
|
|
15460
|
+
const rendererProps = {};
|
|
15461
|
+
for (const key in rendererConfig) {
|
|
15462
|
+
if (!nonApplyProps.includes(key)) rendererProps[key] = rendererConfig[key];
|
|
15463
|
+
}
|
|
15464
|
+
applyProps(currentRenderer, rendererProps);
|
|
15229
15465
|
}
|
|
15230
15466
|
}
|
|
15231
15467
|
const scheduler = getScheduler();
|
|
@@ -15251,6 +15487,18 @@ function createRoot(canvas) {
|
|
|
15251
15487
|
system: true
|
|
15252
15488
|
}
|
|
15253
15489
|
);
|
|
15490
|
+
const unregisterEventsFlush = scheduler.register(
|
|
15491
|
+
() => {
|
|
15492
|
+
const state2 = store.getState();
|
|
15493
|
+
state2.events.flush?.();
|
|
15494
|
+
},
|
|
15495
|
+
{
|
|
15496
|
+
id: `${newRootId}_events`,
|
|
15497
|
+
rootId: newRootId,
|
|
15498
|
+
phase: "input",
|
|
15499
|
+
system: true
|
|
15500
|
+
}
|
|
15501
|
+
);
|
|
15254
15502
|
const unregisterFrustum = scheduler.register(
|
|
15255
15503
|
() => {
|
|
15256
15504
|
const state2 = store.getState();
|
|
@@ -15285,7 +15533,7 @@ function createRoot(canvas) {
|
|
|
15285
15533
|
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
15286
15534
|
if (userHandlesRender || state2.internal.priority) return;
|
|
15287
15535
|
try {
|
|
15288
|
-
if (state2.
|
|
15536
|
+
if (state2.renderPipeline?.render) state2.renderPipeline.render();
|
|
15289
15537
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
15290
15538
|
} catch (error) {
|
|
15291
15539
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -15310,6 +15558,7 @@ function createRoot(canvas) {
|
|
|
15310
15558
|
unregisterRoot: () => {
|
|
15311
15559
|
unregisterRoot();
|
|
15312
15560
|
unregisterCanvasTarget();
|
|
15561
|
+
unregisterEventsFlush();
|
|
15313
15562
|
unregisterFrustum();
|
|
15314
15563
|
unregisterVisibility();
|
|
15315
15564
|
unregisterRender();
|
|
@@ -15475,9 +15724,13 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
15475
15724
|
const store = createWithEqualityFn((set, get) => ({ ...rest, set, get }));
|
|
15476
15725
|
const onMutate = (prev) => store.setState((state2) => inject.current(prev, state2));
|
|
15477
15726
|
onMutate(previousRoot.getState());
|
|
15478
|
-
previousRoot.subscribe(onMutate);
|
|
15479
15727
|
return store;
|
|
15480
15728
|
}, [previousRoot, container]);
|
|
15729
|
+
useIsomorphicLayoutEffect(() => {
|
|
15730
|
+
const onMutate = (prev) => usePortalStore.setState((state2) => inject.current(prev, state2));
|
|
15731
|
+
const unsubscribe = previousRoot.subscribe(onMutate);
|
|
15732
|
+
return unsubscribe;
|
|
15733
|
+
}, [previousRoot, usePortalStore]);
|
|
15481
15734
|
return (
|
|
15482
15735
|
// @ts-ignore, reconciler types are not maintained
|
|
15483
15736
|
/* @__PURE__ */ jsx(Fragment, { children: reconciler.createPortal(
|
|
@@ -15522,8 +15775,18 @@ function CanvasImpl({
|
|
|
15522
15775
|
forceEven,
|
|
15523
15776
|
...props
|
|
15524
15777
|
}) {
|
|
15525
|
-
const
|
|
15526
|
-
|
|
15778
|
+
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
15779
|
+
let primaryCanvas;
|
|
15780
|
+
let scheduler;
|
|
15781
|
+
let renderer;
|
|
15782
|
+
if (isRendererConfig) {
|
|
15783
|
+
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
15784
|
+
primaryCanvas = pc;
|
|
15785
|
+
scheduler = sc;
|
|
15786
|
+
renderer = Object.keys(rest).length > 0 ? rest : rendererProp;
|
|
15787
|
+
} else {
|
|
15788
|
+
renderer = rendererProp;
|
|
15789
|
+
}
|
|
15527
15790
|
React.useMemo(() => extend(THREE), []);
|
|
15528
15791
|
const Bridge = useBridge();
|
|
15529
15792
|
const backgroundProps = React.useMemo(() => {
|
|
@@ -15698,6 +15961,7 @@ function CanvasImpl({
|
|
|
15698
15961
|
queueMicrotask(() => {
|
|
15699
15962
|
const rootEntry = _roots.get(canvas);
|
|
15700
15963
|
if (rootEntry?.store) {
|
|
15964
|
+
console.log("[R3F] HMR detected \u2014 rebuilding nodes/uniforms");
|
|
15701
15965
|
rootEntry.store.setState((state) => ({
|
|
15702
15966
|
nodes: {},
|
|
15703
15967
|
uniforms: {},
|
|
@@ -15709,8 +15973,7 @@ function CanvasImpl({
|
|
|
15709
15973
|
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
15710
15974
|
const hot = import.meta.hot;
|
|
15711
15975
|
hot.on("vite:afterUpdate", handleHMR);
|
|
15712
|
-
return () => hot.
|
|
15713
|
-
});
|
|
15976
|
+
return () => hot.off?.("vite:afterUpdate", handleHMR);
|
|
15714
15977
|
}
|
|
15715
15978
|
if (typeof module !== "undefined" && module.hot) {
|
|
15716
15979
|
const hot = module.hot;
|
|
@@ -15733,7 +15996,16 @@ function CanvasImpl({
|
|
|
15733
15996
|
...style
|
|
15734
15997
|
},
|
|
15735
15998
|
...props,
|
|
15736
|
-
children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
15999
|
+
children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
16000
|
+
"canvas",
|
|
16001
|
+
{
|
|
16002
|
+
ref: canvasRef,
|
|
16003
|
+
id,
|
|
16004
|
+
className: "r3f-canvas",
|
|
16005
|
+
style: { display: "block", width: "100%", height: "100%" },
|
|
16006
|
+
children: fallback
|
|
16007
|
+
}
|
|
16008
|
+
) })
|
|
15737
16009
|
}
|
|
15738
16010
|
);
|
|
15739
16011
|
}
|
|
@@ -15809,6 +16081,8 @@ function createScopedStore(data) {
|
|
|
15809
16081
|
function createLazyCreatorState(state) {
|
|
15810
16082
|
let _uniforms = null;
|
|
15811
16083
|
let _nodes = null;
|
|
16084
|
+
let _buffers = null;
|
|
16085
|
+
let _gpuStorage = null;
|
|
15812
16086
|
return Object.create(state, {
|
|
15813
16087
|
uniforms: {
|
|
15814
16088
|
get() {
|
|
@@ -15819,6 +16093,16 @@ function createLazyCreatorState(state) {
|
|
|
15819
16093
|
get() {
|
|
15820
16094
|
return _nodes ?? (_nodes = createScopedStore(state.nodes));
|
|
15821
16095
|
}
|
|
16096
|
+
},
|
|
16097
|
+
buffers: {
|
|
16098
|
+
get() {
|
|
16099
|
+
return _buffers ?? (_buffers = createScopedStore(state.buffers));
|
|
16100
|
+
}
|
|
16101
|
+
},
|
|
16102
|
+
gpuStorage: {
|
|
16103
|
+
get() {
|
|
16104
|
+
return _gpuStorage ?? (_gpuStorage = createScopedStore(state.gpuStorage));
|
|
16105
|
+
}
|
|
15822
16106
|
}
|
|
15823
16107
|
});
|
|
15824
16108
|
}
|
|
@@ -15901,6 +16185,10 @@ function vectorize(inObject) {
|
|
|
15901
16185
|
if (obj.isVector2 || obj.isVector3 || obj.isVector4) return inObject;
|
|
15902
16186
|
if (obj.isMatrix3 || obj.isMatrix4) return inObject;
|
|
15903
16187
|
if (obj.isColor || obj.isEuler || obj.isQuaternion || obj.isSpherical) return inObject;
|
|
16188
|
+
if ("r" in obj && "g" in obj && "b" in obj && typeof obj.r === "number" && typeof obj.g === "number" && typeof obj.b === "number") {
|
|
16189
|
+
const scale = obj.r > 1 || obj.g > 1 || obj.b > 1 ? 1 / 255 : 1;
|
|
16190
|
+
return new Color(obj.r * scale, obj.g * scale, obj.b * scale);
|
|
16191
|
+
}
|
|
15904
16192
|
if ("x" in obj && "y" in obj && typeof obj.x === "number" && typeof obj.y === "number") {
|
|
15905
16193
|
if ("w" in obj && typeof obj.w === "number" && "z" in obj && typeof obj.z === "number") {
|
|
15906
16194
|
return new Vector4(obj.x, obj.y, obj.z, obj.w);
|
|
@@ -16356,7 +16644,351 @@ function useLocalNodes(creator) {
|
|
|
16356
16644
|
}, [store, creator, uniforms, nodes, textures, hmrVersion]);
|
|
16357
16645
|
}
|
|
16358
16646
|
|
|
16359
|
-
|
|
16647
|
+
const isBufferLike = (value) => {
|
|
16648
|
+
if (value === null || typeof value !== "object") return false;
|
|
16649
|
+
if (ArrayBuffer.isView(value)) return true;
|
|
16650
|
+
if ("isBufferAttribute" in value) return true;
|
|
16651
|
+
if ("uuid" in value || "nodeType" in value) return true;
|
|
16652
|
+
return false;
|
|
16653
|
+
};
|
|
16654
|
+
const disposeBuffer = (buffer) => {
|
|
16655
|
+
if (buffer === null || typeof buffer !== "object") return;
|
|
16656
|
+
if ("dispose" in buffer && typeof buffer.dispose === "function") {
|
|
16657
|
+
buffer.dispose();
|
|
16658
|
+
}
|
|
16659
|
+
};
|
|
16660
|
+
function useBuffers(creatorOrScope, scope) {
|
|
16661
|
+
const store = useStore();
|
|
16662
|
+
const removeBuffers = useCallback(
|
|
16663
|
+
(names, targetScope) => {
|
|
16664
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16665
|
+
store.setState((state) => {
|
|
16666
|
+
if (targetScope) {
|
|
16667
|
+
const currentScope = { ...state.buffers[targetScope] };
|
|
16668
|
+
for (const name of nameArray) delete currentScope[name];
|
|
16669
|
+
return { buffers: { ...state.buffers, [targetScope]: currentScope } };
|
|
16670
|
+
}
|
|
16671
|
+
const buffers2 = { ...state.buffers };
|
|
16672
|
+
for (const name of nameArray) if (isBufferLike(buffers2[name])) delete buffers2[name];
|
|
16673
|
+
return { buffers: buffers2 };
|
|
16674
|
+
});
|
|
16675
|
+
},
|
|
16676
|
+
[store]
|
|
16677
|
+
);
|
|
16678
|
+
const clearBuffers = useCallback(
|
|
16679
|
+
(targetScope) => {
|
|
16680
|
+
store.setState((state) => {
|
|
16681
|
+
if (targetScope && targetScope !== "root") {
|
|
16682
|
+
const { [targetScope]: _, ...rest } = state.buffers;
|
|
16683
|
+
return { buffers: rest };
|
|
16684
|
+
}
|
|
16685
|
+
if (targetScope === "root") {
|
|
16686
|
+
const buffers2 = {};
|
|
16687
|
+
for (const [key, value] of Object.entries(state.buffers)) {
|
|
16688
|
+
if (!isBufferLike(value)) buffers2[key] = value;
|
|
16689
|
+
}
|
|
16690
|
+
return { buffers: buffers2 };
|
|
16691
|
+
}
|
|
16692
|
+
return { buffers: {} };
|
|
16693
|
+
});
|
|
16694
|
+
},
|
|
16695
|
+
[store]
|
|
16696
|
+
);
|
|
16697
|
+
const rebuildBuffers = useCallback(
|
|
16698
|
+
(targetScope) => {
|
|
16699
|
+
store.setState((state) => {
|
|
16700
|
+
let newBuffers = state.buffers;
|
|
16701
|
+
if (targetScope && targetScope !== "root") {
|
|
16702
|
+
const { [targetScope]: _, ...rest } = state.buffers;
|
|
16703
|
+
newBuffers = rest;
|
|
16704
|
+
} else if (targetScope === "root") {
|
|
16705
|
+
newBuffers = {};
|
|
16706
|
+
for (const [key, value] of Object.entries(state.buffers)) {
|
|
16707
|
+
if (!isBufferLike(value)) newBuffers[key] = value;
|
|
16708
|
+
}
|
|
16709
|
+
} else {
|
|
16710
|
+
newBuffers = {};
|
|
16711
|
+
}
|
|
16712
|
+
return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
|
|
16713
|
+
});
|
|
16714
|
+
},
|
|
16715
|
+
[store]
|
|
16716
|
+
);
|
|
16717
|
+
const disposeBuffers = useCallback(
|
|
16718
|
+
(names, targetScope) => {
|
|
16719
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16720
|
+
const state = store.getState();
|
|
16721
|
+
for (const name of nameArray) {
|
|
16722
|
+
const buffer = targetScope ? state.buffers[targetScope]?.[name] : state.buffers[name];
|
|
16723
|
+
if (buffer && isBufferLike(buffer)) {
|
|
16724
|
+
disposeBuffer(buffer);
|
|
16725
|
+
}
|
|
16726
|
+
}
|
|
16727
|
+
removeBuffers(names, targetScope);
|
|
16728
|
+
},
|
|
16729
|
+
[store, removeBuffers]
|
|
16730
|
+
);
|
|
16731
|
+
const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
|
|
16732
|
+
const storeBuffers = useThree((s) => s.buffers);
|
|
16733
|
+
const hmrVersion = useThree((s) => s._hmrVersion);
|
|
16734
|
+
const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
|
|
16735
|
+
const readerDep = isReader ? storeBuffers : null;
|
|
16736
|
+
const creatorDep = isReader ? null : hmrVersion;
|
|
16737
|
+
const buffers = useMemo(() => {
|
|
16738
|
+
if (creatorOrScope === void 0) {
|
|
16739
|
+
return storeBuffers;
|
|
16740
|
+
}
|
|
16741
|
+
if (typeof creatorOrScope === "string") {
|
|
16742
|
+
const scopeData = storeBuffers[creatorOrScope];
|
|
16743
|
+
if (scopeData && !isBufferLike(scopeData)) return scopeData;
|
|
16744
|
+
return {};
|
|
16745
|
+
}
|
|
16746
|
+
const state = store.getState();
|
|
16747
|
+
const set = store.setState;
|
|
16748
|
+
const creator = creatorOrScope;
|
|
16749
|
+
const wrappedState = createLazyCreatorState(state);
|
|
16750
|
+
const created = creator(wrappedState);
|
|
16751
|
+
const result = {};
|
|
16752
|
+
let hasNewBuffers = false;
|
|
16753
|
+
if (scope) {
|
|
16754
|
+
const currentScope = state.buffers[scope] ?? {};
|
|
16755
|
+
for (const [name, buffer] of Object.entries(created)) {
|
|
16756
|
+
if (currentScope[name]) {
|
|
16757
|
+
result[name] = currentScope[name];
|
|
16758
|
+
} else {
|
|
16759
|
+
if ("setName" in buffer && typeof buffer.setName === "function") {
|
|
16760
|
+
buffer.setName(`${scope}.${name}`);
|
|
16761
|
+
}
|
|
16762
|
+
result[name] = buffer;
|
|
16763
|
+
hasNewBuffers = true;
|
|
16764
|
+
}
|
|
16765
|
+
}
|
|
16766
|
+
if (hasNewBuffers) {
|
|
16767
|
+
set((s) => ({
|
|
16768
|
+
buffers: {
|
|
16769
|
+
...s.buffers,
|
|
16770
|
+
[scope]: { ...s.buffers[scope], ...result }
|
|
16771
|
+
}
|
|
16772
|
+
}));
|
|
16773
|
+
}
|
|
16774
|
+
return result;
|
|
16775
|
+
}
|
|
16776
|
+
for (const [name, buffer] of Object.entries(created)) {
|
|
16777
|
+
const existing = state.buffers[name];
|
|
16778
|
+
if (existing && isBufferLike(existing)) {
|
|
16779
|
+
result[name] = existing;
|
|
16780
|
+
} else {
|
|
16781
|
+
if ("setName" in buffer && typeof buffer.setName === "function") {
|
|
16782
|
+
buffer.setName(name);
|
|
16783
|
+
}
|
|
16784
|
+
result[name] = buffer;
|
|
16785
|
+
hasNewBuffers = true;
|
|
16786
|
+
}
|
|
16787
|
+
}
|
|
16788
|
+
if (hasNewBuffers) {
|
|
16789
|
+
set((s) => ({ buffers: { ...s.buffers, ...result } }));
|
|
16790
|
+
}
|
|
16791
|
+
return result;
|
|
16792
|
+
}, [store, scopeDep, readerDep, creatorDep]);
|
|
16793
|
+
return { ...buffers, removeBuffers, clearBuffers, rebuildBuffers, disposeBuffers };
|
|
16794
|
+
}
|
|
16795
|
+
function rebuildAllBuffers(store, scope) {
|
|
16796
|
+
store.setState((state) => {
|
|
16797
|
+
let newBuffers = state.buffers;
|
|
16798
|
+
if (scope && scope !== "root") {
|
|
16799
|
+
const { [scope]: _, ...rest } = state.buffers;
|
|
16800
|
+
newBuffers = rest;
|
|
16801
|
+
} else if (scope === "root") {
|
|
16802
|
+
newBuffers = {};
|
|
16803
|
+
for (const [key, value] of Object.entries(state.buffers)) {
|
|
16804
|
+
if (!isBufferLike(value)) newBuffers[key] = value;
|
|
16805
|
+
}
|
|
16806
|
+
} else {
|
|
16807
|
+
newBuffers = {};
|
|
16808
|
+
}
|
|
16809
|
+
return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
|
|
16810
|
+
});
|
|
16811
|
+
}
|
|
16812
|
+
|
|
16813
|
+
const isStorageLike = (value) => {
|
|
16814
|
+
if (value === null || typeof value !== "object") return false;
|
|
16815
|
+
if ("isTexture" in value) return true;
|
|
16816
|
+
if ("isData3DTexture" in value) return true;
|
|
16817
|
+
if ("uuid" in value || "nodeType" in value) return true;
|
|
16818
|
+
return false;
|
|
16819
|
+
};
|
|
16820
|
+
const disposeStorage = (storage) => {
|
|
16821
|
+
if (storage === null || typeof storage !== "object") return;
|
|
16822
|
+
if ("dispose" in storage && typeof storage.dispose === "function") {
|
|
16823
|
+
storage.dispose();
|
|
16824
|
+
}
|
|
16825
|
+
};
|
|
16826
|
+
function useGPUStorage(creatorOrScope, scope) {
|
|
16827
|
+
const store = useStore();
|
|
16828
|
+
const removeStorage = useCallback(
|
|
16829
|
+
(names, targetScope) => {
|
|
16830
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16831
|
+
store.setState((state) => {
|
|
16832
|
+
if (targetScope) {
|
|
16833
|
+
const currentScope = { ...state.gpuStorage[targetScope] };
|
|
16834
|
+
for (const name of nameArray) delete currentScope[name];
|
|
16835
|
+
return { gpuStorage: { ...state.gpuStorage, [targetScope]: currentScope } };
|
|
16836
|
+
}
|
|
16837
|
+
const gpuStorage2 = { ...state.gpuStorage };
|
|
16838
|
+
for (const name of nameArray) if (isStorageLike(gpuStorage2[name])) delete gpuStorage2[name];
|
|
16839
|
+
return { gpuStorage: gpuStorage2 };
|
|
16840
|
+
});
|
|
16841
|
+
},
|
|
16842
|
+
[store]
|
|
16843
|
+
);
|
|
16844
|
+
const clearStorage = useCallback(
|
|
16845
|
+
(targetScope) => {
|
|
16846
|
+
store.setState((state) => {
|
|
16847
|
+
if (targetScope && targetScope !== "root") {
|
|
16848
|
+
const { [targetScope]: _, ...rest } = state.gpuStorage;
|
|
16849
|
+
return { gpuStorage: rest };
|
|
16850
|
+
}
|
|
16851
|
+
if (targetScope === "root") {
|
|
16852
|
+
const gpuStorage2 = {};
|
|
16853
|
+
for (const [key, value] of Object.entries(state.gpuStorage)) {
|
|
16854
|
+
if (!isStorageLike(value)) gpuStorage2[key] = value;
|
|
16855
|
+
}
|
|
16856
|
+
return { gpuStorage: gpuStorage2 };
|
|
16857
|
+
}
|
|
16858
|
+
return { gpuStorage: {} };
|
|
16859
|
+
});
|
|
16860
|
+
},
|
|
16861
|
+
[store]
|
|
16862
|
+
);
|
|
16863
|
+
const rebuildStorage = useCallback(
|
|
16864
|
+
(targetScope) => {
|
|
16865
|
+
store.setState((state) => {
|
|
16866
|
+
let newStorage = state.gpuStorage;
|
|
16867
|
+
if (targetScope && targetScope !== "root") {
|
|
16868
|
+
const { [targetScope]: _, ...rest } = state.gpuStorage;
|
|
16869
|
+
newStorage = rest;
|
|
16870
|
+
} else if (targetScope === "root") {
|
|
16871
|
+
newStorage = {};
|
|
16872
|
+
for (const [key, value] of Object.entries(state.gpuStorage)) {
|
|
16873
|
+
if (!isStorageLike(value)) newStorage[key] = value;
|
|
16874
|
+
}
|
|
16875
|
+
} else {
|
|
16876
|
+
newStorage = {};
|
|
16877
|
+
}
|
|
16878
|
+
return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
|
|
16879
|
+
});
|
|
16880
|
+
},
|
|
16881
|
+
[store]
|
|
16882
|
+
);
|
|
16883
|
+
const disposeStorageFn = useCallback(
|
|
16884
|
+
(names, targetScope) => {
|
|
16885
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16886
|
+
const state = store.getState();
|
|
16887
|
+
for (const name of nameArray) {
|
|
16888
|
+
const storage = targetScope ? state.gpuStorage[targetScope]?.[name] : state.gpuStorage[name];
|
|
16889
|
+
if (storage && isStorageLike(storage)) {
|
|
16890
|
+
disposeStorage(storage);
|
|
16891
|
+
}
|
|
16892
|
+
}
|
|
16893
|
+
removeStorage(names, targetScope);
|
|
16894
|
+
},
|
|
16895
|
+
[store, removeStorage]
|
|
16896
|
+
);
|
|
16897
|
+
const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
|
|
16898
|
+
const storeStorage = useThree((s) => s.gpuStorage);
|
|
16899
|
+
const hmrVersion = useThree((s) => s._hmrVersion);
|
|
16900
|
+
const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
|
|
16901
|
+
const readerDep = isReader ? storeStorage : null;
|
|
16902
|
+
const creatorDep = isReader ? null : hmrVersion;
|
|
16903
|
+
const gpuStorage = useMemo(() => {
|
|
16904
|
+
if (creatorOrScope === void 0) {
|
|
16905
|
+
return storeStorage;
|
|
16906
|
+
}
|
|
16907
|
+
if (typeof creatorOrScope === "string") {
|
|
16908
|
+
const scopeData = storeStorage[creatorOrScope];
|
|
16909
|
+
if (scopeData && !isStorageLike(scopeData)) return scopeData;
|
|
16910
|
+
return {};
|
|
16911
|
+
}
|
|
16912
|
+
const state = store.getState();
|
|
16913
|
+
const set = store.setState;
|
|
16914
|
+
const creator = creatorOrScope;
|
|
16915
|
+
const wrappedState = createLazyCreatorState(state);
|
|
16916
|
+
const created = creator(wrappedState);
|
|
16917
|
+
const result = {};
|
|
16918
|
+
let hasNewStorage = false;
|
|
16919
|
+
if (scope) {
|
|
16920
|
+
const currentScope = state.gpuStorage[scope] ?? {};
|
|
16921
|
+
for (const [name, storage] of Object.entries(created)) {
|
|
16922
|
+
if (currentScope[name]) {
|
|
16923
|
+
result[name] = currentScope[name];
|
|
16924
|
+
} else {
|
|
16925
|
+
if ("setName" in storage && typeof storage.setName === "function") {
|
|
16926
|
+
storage.setName(`${scope}.${name}`);
|
|
16927
|
+
}
|
|
16928
|
+
if ("name" in storage && typeof storage.name === "string") {
|
|
16929
|
+
storage.name = `${scope}.${name}`;
|
|
16930
|
+
}
|
|
16931
|
+
result[name] = storage;
|
|
16932
|
+
hasNewStorage = true;
|
|
16933
|
+
}
|
|
16934
|
+
}
|
|
16935
|
+
if (hasNewStorage) {
|
|
16936
|
+
set((s) => ({
|
|
16937
|
+
gpuStorage: {
|
|
16938
|
+
...s.gpuStorage,
|
|
16939
|
+
[scope]: { ...s.gpuStorage[scope], ...result }
|
|
16940
|
+
}
|
|
16941
|
+
}));
|
|
16942
|
+
}
|
|
16943
|
+
return result;
|
|
16944
|
+
}
|
|
16945
|
+
for (const [name, storage] of Object.entries(created)) {
|
|
16946
|
+
const existing = state.gpuStorage[name];
|
|
16947
|
+
if (existing && isStorageLike(existing)) {
|
|
16948
|
+
result[name] = existing;
|
|
16949
|
+
} else {
|
|
16950
|
+
if ("setName" in storage && typeof storage.setName === "function") {
|
|
16951
|
+
storage.setName(name);
|
|
16952
|
+
}
|
|
16953
|
+
if ("name" in storage && typeof storage.name === "string") {
|
|
16954
|
+
storage.name = name;
|
|
16955
|
+
}
|
|
16956
|
+
result[name] = storage;
|
|
16957
|
+
hasNewStorage = true;
|
|
16958
|
+
}
|
|
16959
|
+
}
|
|
16960
|
+
if (hasNewStorage) {
|
|
16961
|
+
set((s) => ({ gpuStorage: { ...s.gpuStorage, ...result } }));
|
|
16962
|
+
}
|
|
16963
|
+
return result;
|
|
16964
|
+
}, [store, scopeDep, readerDep, creatorDep]);
|
|
16965
|
+
return {
|
|
16966
|
+
...gpuStorage,
|
|
16967
|
+
removeStorage,
|
|
16968
|
+
clearStorage,
|
|
16969
|
+
rebuildStorage,
|
|
16970
|
+
disposeStorage: disposeStorageFn
|
|
16971
|
+
};
|
|
16972
|
+
}
|
|
16973
|
+
function rebuildAllStorage(store, scope) {
|
|
16974
|
+
store.setState((state) => {
|
|
16975
|
+
let newStorage = state.gpuStorage;
|
|
16976
|
+
if (scope && scope !== "root") {
|
|
16977
|
+
const { [scope]: _, ...rest } = state.gpuStorage;
|
|
16978
|
+
newStorage = rest;
|
|
16979
|
+
} else if (scope === "root") {
|
|
16980
|
+
newStorage = {};
|
|
16981
|
+
for (const [key, value] of Object.entries(state.gpuStorage)) {
|
|
16982
|
+
if (!isStorageLike(value)) newStorage[key] = value;
|
|
16983
|
+
}
|
|
16984
|
+
} else {
|
|
16985
|
+
newStorage = {};
|
|
16986
|
+
}
|
|
16987
|
+
return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
|
|
16988
|
+
});
|
|
16989
|
+
}
|
|
16990
|
+
|
|
16991
|
+
function useRenderPipeline(mainCB, setupCB) {
|
|
16360
16992
|
const store = useStore();
|
|
16361
16993
|
const { scene, camera, renderer, isLegacy } = useThree();
|
|
16362
16994
|
const callbacksRanRef = useRef(false);
|
|
@@ -16375,7 +17007,7 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16375
17007
|
}, [store]);
|
|
16376
17008
|
const reset = useCallback(() => {
|
|
16377
17009
|
store.setState({
|
|
16378
|
-
|
|
17010
|
+
renderPipeline: null,
|
|
16379
17011
|
passes: {}
|
|
16380
17012
|
});
|
|
16381
17013
|
callbacksRanRef.current = false;
|
|
@@ -16388,13 +17020,13 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16388
17020
|
}, []);
|
|
16389
17021
|
useLayoutEffect(() => {
|
|
16390
17022
|
if (isLegacy) {
|
|
16391
|
-
throw new Error("
|
|
17023
|
+
throw new Error("useRenderPipeline is only available with WebGPU renderer. Set renderer prop on Canvas.");
|
|
16392
17024
|
}
|
|
16393
17025
|
if (!renderer || !scene || !camera) return;
|
|
16394
17026
|
const state = store.getState();
|
|
16395
17027
|
const set = store.setState;
|
|
16396
17028
|
try {
|
|
16397
|
-
let pp = state.
|
|
17029
|
+
let pp = state.renderPipeline;
|
|
16398
17030
|
let currentPasses = { ...state.passes };
|
|
16399
17031
|
let justCreatedPP = false;
|
|
16400
17032
|
if (!pp) {
|
|
@@ -16411,7 +17043,7 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16411
17043
|
}
|
|
16412
17044
|
currentPasses.scenePass = scenePass;
|
|
16413
17045
|
if (!pp.outputNode || justCreatedPP) pp.outputNode = scenePass;
|
|
16414
|
-
set({
|
|
17046
|
+
set({ renderPipeline: pp, passes: currentPasses });
|
|
16415
17047
|
const shouldRunCallbacks = justCreatedPP || !callbacksRanRef.current || !cacheValid;
|
|
16416
17048
|
if (shouldRunCallbacks) {
|
|
16417
17049
|
if (setupCBRef.current) {
|
|
@@ -16433,22 +17065,22 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16433
17065
|
callbacksRanRef.current = true;
|
|
16434
17066
|
}
|
|
16435
17067
|
} catch (error) {
|
|
16436
|
-
console.error("[
|
|
17068
|
+
console.error("[useRenderPipeline] Setup error:", error);
|
|
16437
17069
|
}
|
|
16438
17070
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16439
17071
|
const passes = useThree((s) => s.passes);
|
|
16440
|
-
const
|
|
17072
|
+
const renderPipeline = useThree((s) => s.renderPipeline);
|
|
16441
17073
|
return {
|
|
16442
17074
|
passes,
|
|
16443
|
-
|
|
17075
|
+
renderPipeline,
|
|
16444
17076
|
clearPasses,
|
|
16445
17077
|
reset,
|
|
16446
17078
|
rebuild,
|
|
16447
|
-
// isReady indicates if
|
|
16448
|
-
isReady:
|
|
17079
|
+
// isReady indicates if RenderPipeline is configured and ready for rendering
|
|
17080
|
+
isReady: renderPipeline !== null
|
|
16449
17081
|
};
|
|
16450
17082
|
}
|
|
16451
17083
|
|
|
16452
17084
|
extend(THREE);
|
|
16453
17085
|
|
|
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,
|
|
17086
|
+
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, rebuildAllBuffers, rebuildAllNodes, rebuildAllStorage, rebuildAllUniforms, reconciler, registerPrimary, removeInteractivity, removeNodes, removeUniforms, resolve, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useBuffers, useEnvironment, useFrame, useGPUStorage, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useLocalNodes, useMutableCallback, useNodes, useRenderPipeline, useRenderTarget, useStore, useTexture, useTextures, useThree, useUniform, useUniforms, waitForPrimary };
|