@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.cjs
CHANGED
|
@@ -170,7 +170,7 @@ function useEnvironment({
|
|
|
170
170
|
fiber.useLoader.clear(loader, multiFile ? [files] : files);
|
|
171
171
|
}
|
|
172
172
|
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
173
|
-
}, [files, renderer.domElement]);
|
|
173
|
+
}, [extension, files, loader, multiFile, renderer.domElement]);
|
|
174
174
|
const loaderResult = fiber.useLoader(
|
|
175
175
|
loader,
|
|
176
176
|
multiFile ? [files] : files,
|
|
@@ -370,7 +370,22 @@ function EnvironmentPortal({
|
|
|
370
370
|
environmentIntensity,
|
|
371
371
|
environmentRotation
|
|
372
372
|
});
|
|
373
|
-
}, [
|
|
373
|
+
}, [
|
|
374
|
+
children,
|
|
375
|
+
virtualScene,
|
|
376
|
+
fbo.texture,
|
|
377
|
+
scene,
|
|
378
|
+
defaultScene,
|
|
379
|
+
background,
|
|
380
|
+
frames,
|
|
381
|
+
gl,
|
|
382
|
+
blur,
|
|
383
|
+
backgroundBlurriness,
|
|
384
|
+
backgroundIntensity,
|
|
385
|
+
backgroundRotation,
|
|
386
|
+
environmentIntensity,
|
|
387
|
+
environmentRotation
|
|
388
|
+
]);
|
|
374
389
|
let count = 1;
|
|
375
390
|
fiber.useFrame(() => {
|
|
376
391
|
if (frames === Infinity || count < frames) {
|
|
@@ -1006,6 +1021,9 @@ function applyProps(object, props) {
|
|
|
1006
1021
|
else target.set(value);
|
|
1007
1022
|
} else {
|
|
1008
1023
|
root[key] = value;
|
|
1024
|
+
if (key.endsWith("Node") && root.isMaterial) {
|
|
1025
|
+
root.needsUpdate = true;
|
|
1026
|
+
}
|
|
1009
1027
|
if (rootState && rootState.renderer?.outputColorSpace === webgpu.SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
1010
1028
|
root[key].format === webgpu.RGBAFormat && root[key].type === webgpu.UnsignedByteType) {
|
|
1011
1029
|
root[key].colorSpace = rootState.textureColorSpace;
|
|
@@ -1039,38 +1057,60 @@ function applyProps(object, props) {
|
|
|
1039
1057
|
return object;
|
|
1040
1058
|
}
|
|
1041
1059
|
|
|
1060
|
+
const DEFAULT_POINTER_ID = 0;
|
|
1061
|
+
const XR_POINTER_ID_START = 1e3;
|
|
1062
|
+
function getPointerState(internal, pointerId) {
|
|
1063
|
+
let state = internal.pointerMap.get(pointerId);
|
|
1064
|
+
if (!state) {
|
|
1065
|
+
state = {
|
|
1066
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
1067
|
+
captured: /* @__PURE__ */ new Map(),
|
|
1068
|
+
initialClick: [0, 0],
|
|
1069
|
+
initialHits: []
|
|
1070
|
+
};
|
|
1071
|
+
internal.pointerMap.set(pointerId, state);
|
|
1072
|
+
}
|
|
1073
|
+
return state;
|
|
1074
|
+
}
|
|
1075
|
+
function getPointerId(event) {
|
|
1076
|
+
return "pointerId" in event ? event.pointerId : DEFAULT_POINTER_ID;
|
|
1077
|
+
}
|
|
1042
1078
|
function makeId(event) {
|
|
1043
1079
|
return (event.eventObject || event.object).uuid + "/" + event.index + event.instanceId;
|
|
1044
1080
|
}
|
|
1045
|
-
function releaseInternalPointerCapture(
|
|
1046
|
-
const
|
|
1081
|
+
function releaseInternalPointerCapture(internal, obj, pointerId) {
|
|
1082
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1083
|
+
if (!pointerState) return;
|
|
1084
|
+
const captureData = pointerState.captured.get(obj);
|
|
1047
1085
|
if (captureData) {
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
capturedMap.delete(pointerId);
|
|
1051
|
-
captureData.target.releasePointerCapture(pointerId);
|
|
1052
|
-
}
|
|
1086
|
+
pointerState.captured.delete(obj);
|
|
1087
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
1053
1088
|
}
|
|
1054
1089
|
}
|
|
1055
1090
|
function removeInteractivity(store, object) {
|
|
1056
1091
|
const { internal } = store.getState();
|
|
1057
1092
|
internal.interaction = internal.interaction.filter((o) => o !== object);
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1093
|
+
for (const [pointerId, pointerState] of internal.pointerMap) {
|
|
1094
|
+
pointerState.initialHits = pointerState.initialHits.filter((o) => o !== object);
|
|
1095
|
+
pointerState.hovered.forEach((value, key) => {
|
|
1096
|
+
if (value.eventObject === object || value.object === object) {
|
|
1097
|
+
pointerState.hovered.delete(key);
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
if (pointerState.captured.has(object)) {
|
|
1101
|
+
releaseInternalPointerCapture(internal, object, pointerId);
|
|
1062
1102
|
}
|
|
1063
|
-
}
|
|
1064
|
-
internal.capturedMap.forEach((captures, pointerId) => {
|
|
1065
|
-
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
1066
|
-
});
|
|
1103
|
+
}
|
|
1067
1104
|
unregisterVisibility(store, object);
|
|
1068
1105
|
}
|
|
1069
1106
|
function createEvents(store) {
|
|
1070
|
-
function calculateDistance(event) {
|
|
1107
|
+
function calculateDistance(event, pointerId) {
|
|
1071
1108
|
const { internal } = store.getState();
|
|
1072
|
-
const
|
|
1073
|
-
|
|
1109
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1110
|
+
if (!pointerState) return 0;
|
|
1111
|
+
const [initialX, initialY] = pointerState.initialClick;
|
|
1112
|
+
const dx = event.offsetX - initialX;
|
|
1113
|
+
const dy = event.offsetY - initialY;
|
|
1074
1114
|
return Math.round(Math.sqrt(dx * dx + dy * dy));
|
|
1075
1115
|
}
|
|
1076
1116
|
function filterPointerEvents(objects) {
|
|
@@ -1106,6 +1146,15 @@ function createEvents(store) {
|
|
|
1106
1146
|
return state2.raycaster.camera ? state2.raycaster.intersectObject(obj, true) : [];
|
|
1107
1147
|
}
|
|
1108
1148
|
let hits = eventsObjects.flatMap(handleRaycast).sort((a, b) => {
|
|
1149
|
+
const aInteractivePriority = a.object.userData?.interactivePriority;
|
|
1150
|
+
const bInteractivePriority = b.object.userData?.interactivePriority;
|
|
1151
|
+
if (aInteractivePriority !== void 0 || bInteractivePriority !== void 0) {
|
|
1152
|
+
if (aInteractivePriority !== void 0 && bInteractivePriority === void 0) return -1;
|
|
1153
|
+
if (bInteractivePriority !== void 0 && aInteractivePriority === void 0) return 1;
|
|
1154
|
+
if (aInteractivePriority !== bInteractivePriority) {
|
|
1155
|
+
return (bInteractivePriority ?? 0) - (aInteractivePriority ?? 0);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1109
1158
|
const aState = getRootState(a.object);
|
|
1110
1159
|
const bState = getRootState(b.object);
|
|
1111
1160
|
const aPriority = aState?.events?.priority ?? 1;
|
|
@@ -1127,9 +1176,13 @@ function createEvents(store) {
|
|
|
1127
1176
|
eventObject = eventObject.parent;
|
|
1128
1177
|
}
|
|
1129
1178
|
}
|
|
1130
|
-
if ("pointerId" in event
|
|
1131
|
-
|
|
1132
|
-
|
|
1179
|
+
if ("pointerId" in event) {
|
|
1180
|
+
const pointerId = event.pointerId;
|
|
1181
|
+
const pointerState = state.internal.pointerMap.get(pointerId);
|
|
1182
|
+
if (pointerState?.captured.size) {
|
|
1183
|
+
for (const captureData of pointerState.captured.values()) {
|
|
1184
|
+
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
1185
|
+
}
|
|
1133
1186
|
}
|
|
1134
1187
|
}
|
|
1135
1188
|
return intersections;
|
|
@@ -1142,27 +1195,25 @@ function createEvents(store) {
|
|
|
1142
1195
|
if (state) {
|
|
1143
1196
|
const { raycaster, pointer, camera, internal } = state;
|
|
1144
1197
|
const unprojectedPoint = new webgpu.Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
1145
|
-
const hasPointerCapture = (id) =>
|
|
1198
|
+
const hasPointerCapture = (id) => {
|
|
1199
|
+
const pointerState = internal.pointerMap.get(id);
|
|
1200
|
+
return pointerState?.captured.has(hit.eventObject) ?? false;
|
|
1201
|
+
};
|
|
1146
1202
|
const setPointerCapture = (id) => {
|
|
1147
1203
|
const captureData = { intersection: hit, target: event.target };
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
} else {
|
|
1151
|
-
internal.capturedMap.set(id, /* @__PURE__ */ new Map([[hit.eventObject, captureData]]));
|
|
1152
|
-
}
|
|
1204
|
+
const pointerState = getPointerState(internal, id);
|
|
1205
|
+
pointerState.captured.set(hit.eventObject, captureData);
|
|
1153
1206
|
event.target.setPointerCapture(id);
|
|
1154
1207
|
};
|
|
1155
1208
|
const releasePointerCapture = (id) => {
|
|
1156
|
-
|
|
1157
|
-
if (captures) {
|
|
1158
|
-
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
1159
|
-
}
|
|
1209
|
+
releaseInternalPointerCapture(internal, hit.eventObject, id);
|
|
1160
1210
|
};
|
|
1161
1211
|
const extractEventProps = {};
|
|
1162
1212
|
for (const prop in event) {
|
|
1163
1213
|
const property = event[prop];
|
|
1164
1214
|
if (typeof property !== "function") extractEventProps[prop] = property;
|
|
1165
1215
|
}
|
|
1216
|
+
const eventPointerId = "pointerId" in event ? event.pointerId : void 0;
|
|
1166
1217
|
const raycastEvent = {
|
|
1167
1218
|
...hit,
|
|
1168
1219
|
...extractEventProps,
|
|
@@ -1173,18 +1224,19 @@ function createEvents(store) {
|
|
|
1173
1224
|
unprojectedPoint,
|
|
1174
1225
|
ray: raycaster.ray,
|
|
1175
1226
|
camera,
|
|
1227
|
+
pointerId: eventPointerId,
|
|
1176
1228
|
// Hijack stopPropagation, which just sets a flag
|
|
1177
1229
|
stopPropagation() {
|
|
1178
|
-
const
|
|
1230
|
+
const pointerState = eventPointerId !== void 0 ? internal.pointerMap.get(eventPointerId) : void 0;
|
|
1179
1231
|
if (
|
|
1180
1232
|
// ...if this pointer hasn't been captured
|
|
1181
|
-
!
|
|
1182
|
-
|
|
1233
|
+
!pointerState?.captured.size || // ... or if the hit object is capturing the pointer
|
|
1234
|
+
pointerState.captured.has(hit.eventObject)
|
|
1183
1235
|
) {
|
|
1184
1236
|
raycastEvent.stopped = localState.stopped = true;
|
|
1185
|
-
if (
|
|
1237
|
+
if (pointerState?.hovered.size && Array.from(pointerState.hovered.values()).find((i) => i.eventObject === hit.eventObject)) {
|
|
1186
1238
|
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
1187
|
-
cancelPointer([...higher, hit]);
|
|
1239
|
+
cancelPointer([...higher, hit], eventPointerId);
|
|
1188
1240
|
}
|
|
1189
1241
|
}
|
|
1190
1242
|
},
|
|
@@ -1200,15 +1252,18 @@ function createEvents(store) {
|
|
|
1200
1252
|
}
|
|
1201
1253
|
return intersections;
|
|
1202
1254
|
}
|
|
1203
|
-
function cancelPointer(intersections) {
|
|
1255
|
+
function cancelPointer(intersections, pointerId) {
|
|
1204
1256
|
const { internal } = store.getState();
|
|
1205
|
-
|
|
1257
|
+
const pid = pointerId ?? DEFAULT_POINTER_ID;
|
|
1258
|
+
const pointerState = internal.pointerMap.get(pid);
|
|
1259
|
+
if (!pointerState) return;
|
|
1260
|
+
for (const [hoveredId, hoveredObj] of pointerState.hovered) {
|
|
1206
1261
|
if (!intersections.length || !intersections.find(
|
|
1207
1262
|
(hit) => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId
|
|
1208
1263
|
)) {
|
|
1209
1264
|
const eventObject = hoveredObj.eventObject;
|
|
1210
1265
|
const instance = eventObject.__r3f;
|
|
1211
|
-
|
|
1266
|
+
pointerState.hovered.delete(hoveredId);
|
|
1212
1267
|
if (instance?.eventCount) {
|
|
1213
1268
|
const handlers = instance.handlers;
|
|
1214
1269
|
const data = { ...hoveredObj, intersections };
|
|
@@ -1237,41 +1292,118 @@ function createEvents(store) {
|
|
|
1237
1292
|
instance?.handlers.onDropMissed?.(event);
|
|
1238
1293
|
}
|
|
1239
1294
|
}
|
|
1295
|
+
function cleanupPointer(pointerId) {
|
|
1296
|
+
const { internal } = store.getState();
|
|
1297
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1298
|
+
if (pointerState) {
|
|
1299
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1300
|
+
const eventObject = hoveredObj.eventObject;
|
|
1301
|
+
const instance = eventObject.__r3f;
|
|
1302
|
+
if (instance?.eventCount) {
|
|
1303
|
+
const handlers = instance.handlers;
|
|
1304
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1305
|
+
handlers.onPointerOut?.(data);
|
|
1306
|
+
handlers.onPointerLeave?.(data);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
internal.pointerMap.delete(pointerId);
|
|
1310
|
+
}
|
|
1311
|
+
internal.pointerDirty.delete(pointerId);
|
|
1312
|
+
}
|
|
1313
|
+
function processDeferredPointer(event, pointerId) {
|
|
1314
|
+
const state = store.getState();
|
|
1315
|
+
const { internal } = state;
|
|
1316
|
+
if (!state.events.enabled) return;
|
|
1317
|
+
const filter = filterPointerEvents;
|
|
1318
|
+
const hits = intersect(event, filter);
|
|
1319
|
+
cancelPointer(hits, pointerId);
|
|
1320
|
+
function onIntersect(data) {
|
|
1321
|
+
const eventObject = data.eventObject;
|
|
1322
|
+
const instance = eventObject.__r3f;
|
|
1323
|
+
if (!instance?.eventCount) return;
|
|
1324
|
+
const handlers = instance.handlers;
|
|
1325
|
+
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
1326
|
+
const id = makeId(data);
|
|
1327
|
+
const pointerState = getPointerState(internal, pointerId);
|
|
1328
|
+
const hoveredItem = pointerState.hovered.get(id);
|
|
1329
|
+
if (!hoveredItem) {
|
|
1330
|
+
pointerState.hovered.set(id, data);
|
|
1331
|
+
handlers.onPointerOver?.(data);
|
|
1332
|
+
handlers.onPointerEnter?.(data);
|
|
1333
|
+
} else if (hoveredItem.stopped) {
|
|
1334
|
+
data.stopPropagation();
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
handlers.onPointerMove?.(data);
|
|
1338
|
+
}
|
|
1339
|
+
handleIntersects(hits, event, 0, onIntersect);
|
|
1340
|
+
}
|
|
1240
1341
|
function handlePointer(name) {
|
|
1241
1342
|
switch (name) {
|
|
1242
1343
|
case "onPointerLeave":
|
|
1243
|
-
case "onPointerCancel":
|
|
1244
1344
|
case "onDragLeave":
|
|
1245
1345
|
return () => cancelPointer([]);
|
|
1346
|
+
// Global cancel of these events
|
|
1347
|
+
case "onPointerCancel":
|
|
1348
|
+
return (event) => {
|
|
1349
|
+
const pointerId = getPointerId(event);
|
|
1350
|
+
cleanupPointer(pointerId);
|
|
1351
|
+
};
|
|
1246
1352
|
case "onLostPointerCapture":
|
|
1247
1353
|
return (event) => {
|
|
1248
1354
|
const { internal } = store.getState();
|
|
1249
|
-
|
|
1355
|
+
const pointerId = getPointerId(event);
|
|
1356
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1357
|
+
if (pointerState?.captured.size) {
|
|
1250
1358
|
requestAnimationFrame(() => {
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1359
|
+
const pointerState2 = internal.pointerMap.get(pointerId);
|
|
1360
|
+
if (pointerState2?.captured.size) {
|
|
1361
|
+
pointerState2.captured.clear();
|
|
1254
1362
|
}
|
|
1363
|
+
cancelPointer([], pointerId);
|
|
1255
1364
|
});
|
|
1256
1365
|
}
|
|
1257
1366
|
};
|
|
1258
1367
|
}
|
|
1259
1368
|
return function handleEvent(event) {
|
|
1260
1369
|
const state = store.getState();
|
|
1261
|
-
const { onPointerMissed, onDragOverMissed, onDropMissed, internal } = state;
|
|
1370
|
+
const { onPointerMissed, onDragOverMissed, onDropMissed, internal, events } = state;
|
|
1371
|
+
const pointerId = getPointerId(event);
|
|
1262
1372
|
internal.lastEvent.current = event;
|
|
1263
|
-
if (!
|
|
1373
|
+
if (!events.enabled) return;
|
|
1264
1374
|
const isPointerMove = name === "onPointerMove";
|
|
1265
1375
|
const isDragOver = name === "onDragOver";
|
|
1266
1376
|
const isDrop = name === "onDrop";
|
|
1267
1377
|
const isClickEvent = name === "onClick" || name === "onContextMenu" || name === "onDoubleClick";
|
|
1378
|
+
const isPointerDown = name === "onPointerDown";
|
|
1379
|
+
const isPointerUp = name === "onPointerUp";
|
|
1380
|
+
const isWheel = name === "onWheel";
|
|
1381
|
+
const canDeferRaycasts = events.frameTimedRaycasts && state.frameloop === "always";
|
|
1382
|
+
if (isPointerMove && canDeferRaycasts) {
|
|
1383
|
+
events.compute?.(event, state);
|
|
1384
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
if (isWheel && canDeferRaycasts && !events.alwaysFireOnScroll) {
|
|
1388
|
+
events.compute?.(event, state);
|
|
1389
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
if ((isClickEvent || isPointerDown || isPointerUp) && internal.pointerDirty.has(pointerId)) {
|
|
1393
|
+
const deferredEvent = internal.pointerDirty.get(pointerId);
|
|
1394
|
+
internal.pointerDirty.delete(pointerId);
|
|
1395
|
+
processDeferredPointer(deferredEvent, pointerId);
|
|
1396
|
+
}
|
|
1268
1397
|
const filter = isPointerMove || isDragOver || isDrop ? filterPointerEvents : void 0;
|
|
1269
1398
|
const hits = intersect(event, filter);
|
|
1270
|
-
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
1271
|
-
if (
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1399
|
+
const delta = isClickEvent ? calculateDistance(event, pointerId) : 0;
|
|
1400
|
+
if (isPointerDown) {
|
|
1401
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1402
|
+
pointerState2.initialClick = [event.offsetX, event.offsetY];
|
|
1403
|
+
pointerState2.initialHits = hits.map((hit) => hit.eventObject);
|
|
1404
|
+
}
|
|
1405
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1406
|
+
const initialHits = pointerState?.initialHits ?? [];
|
|
1275
1407
|
if (isClickEvent && !hits.length) {
|
|
1276
1408
|
if (delta <= 2) {
|
|
1277
1409
|
pointerMissed(event, internal.interaction);
|
|
@@ -1286,7 +1418,9 @@ function createEvents(store) {
|
|
|
1286
1418
|
dropMissed(event, internal.interaction);
|
|
1287
1419
|
if (onDropMissed) onDropMissed(event);
|
|
1288
1420
|
}
|
|
1289
|
-
if (isPointerMove || isDragOver)
|
|
1421
|
+
if (isPointerMove || isDragOver) {
|
|
1422
|
+
cancelPointer(hits, pointerId);
|
|
1423
|
+
}
|
|
1290
1424
|
function onIntersect(data) {
|
|
1291
1425
|
const eventObject = data.eventObject;
|
|
1292
1426
|
const instance = eventObject.__r3f;
|
|
@@ -1295,9 +1429,10 @@ function createEvents(store) {
|
|
|
1295
1429
|
if (isPointerMove) {
|
|
1296
1430
|
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
1297
1431
|
const id = makeId(data);
|
|
1298
|
-
const
|
|
1432
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1433
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
1299
1434
|
if (!hoveredItem) {
|
|
1300
|
-
|
|
1435
|
+
pointerState2.hovered.set(id, data);
|
|
1301
1436
|
handlers.onPointerOver?.(data);
|
|
1302
1437
|
handlers.onPointerEnter?.(data);
|
|
1303
1438
|
} else if (hoveredItem.stopped) {
|
|
@@ -1307,9 +1442,10 @@ function createEvents(store) {
|
|
|
1307
1442
|
handlers.onPointerMove?.(data);
|
|
1308
1443
|
} else if (isDragOver) {
|
|
1309
1444
|
const id = makeId(data);
|
|
1310
|
-
const
|
|
1445
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1446
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
1311
1447
|
if (!hoveredItem) {
|
|
1312
|
-
|
|
1448
|
+
pointerState2.hovered.set(id, data);
|
|
1313
1449
|
handlers.onDragOverEnter?.(data);
|
|
1314
1450
|
} else if (hoveredItem.stopped) {
|
|
1315
1451
|
data.stopPropagation();
|
|
@@ -1320,18 +1456,18 @@ function createEvents(store) {
|
|
|
1320
1456
|
} else {
|
|
1321
1457
|
const handler = handlers[name];
|
|
1322
1458
|
if (handler) {
|
|
1323
|
-
if (!isClickEvent ||
|
|
1459
|
+
if (!isClickEvent || initialHits.includes(eventObject)) {
|
|
1324
1460
|
pointerMissed(
|
|
1325
1461
|
event,
|
|
1326
|
-
internal.interaction.filter((object) => !
|
|
1462
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
1327
1463
|
);
|
|
1328
1464
|
handler(data);
|
|
1329
1465
|
}
|
|
1330
1466
|
} else {
|
|
1331
|
-
if (isClickEvent &&
|
|
1467
|
+
if (isClickEvent && initialHits.includes(eventObject)) {
|
|
1332
1468
|
pointerMissed(
|
|
1333
1469
|
event,
|
|
1334
|
-
internal.interaction.filter((object) => !
|
|
1470
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
1335
1471
|
);
|
|
1336
1472
|
}
|
|
1337
1473
|
}
|
|
@@ -1340,7 +1476,15 @@ function createEvents(store) {
|
|
|
1340
1476
|
handleIntersects(hits, event, delta, onIntersect);
|
|
1341
1477
|
};
|
|
1342
1478
|
}
|
|
1343
|
-
|
|
1479
|
+
function flushDeferredPointers() {
|
|
1480
|
+
const { internal, events } = store.getState();
|
|
1481
|
+
if (!events.frameTimedRaycasts) return;
|
|
1482
|
+
for (const [pointerId, event] of internal.pointerDirty) {
|
|
1483
|
+
processDeferredPointer(event, pointerId);
|
|
1484
|
+
}
|
|
1485
|
+
internal.pointerDirty.clear();
|
|
1486
|
+
}
|
|
1487
|
+
return { handlePointer, flushDeferredPointers, processDeferredPointer };
|
|
1344
1488
|
}
|
|
1345
1489
|
const DOM_EVENTS = {
|
|
1346
1490
|
onClick: ["click", false],
|
|
@@ -1359,10 +1503,15 @@ const DOM_EVENTS = {
|
|
|
1359
1503
|
onLostPointerCapture: ["lostpointercapture", true]
|
|
1360
1504
|
};
|
|
1361
1505
|
function createPointerEvents(store) {
|
|
1362
|
-
const { handlePointer } = createEvents(store);
|
|
1506
|
+
const { handlePointer, flushDeferredPointers, processDeferredPointer } = createEvents(store);
|
|
1507
|
+
let nextXRPointerId = XR_POINTER_ID_START;
|
|
1508
|
+
const xrPointers = /* @__PURE__ */ new Map();
|
|
1363
1509
|
return {
|
|
1364
1510
|
priority: 1,
|
|
1365
1511
|
enabled: true,
|
|
1512
|
+
frameTimedRaycasts: true,
|
|
1513
|
+
alwaysFireOnScroll: true,
|
|
1514
|
+
updateOnFrame: false,
|
|
1366
1515
|
compute(event, state) {
|
|
1367
1516
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
1368
1517
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
@@ -1372,11 +1521,33 @@ function createPointerEvents(store) {
|
|
|
1372
1521
|
(acc, key) => ({ ...acc, [key]: handlePointer(key) }),
|
|
1373
1522
|
{}
|
|
1374
1523
|
),
|
|
1375
|
-
update: () => {
|
|
1524
|
+
update: (pointerId) => {
|
|
1376
1525
|
const { events, internal } = store.getState();
|
|
1377
|
-
if (
|
|
1526
|
+
if (!events.handlers) return;
|
|
1527
|
+
if (pointerId !== void 0) {
|
|
1528
|
+
const event = internal.pointerDirty.get(pointerId);
|
|
1529
|
+
if (event) {
|
|
1530
|
+
internal.pointerDirty.delete(pointerId);
|
|
1531
|
+
processDeferredPointer(event, pointerId);
|
|
1532
|
+
} else if (internal.lastEvent?.current) {
|
|
1533
|
+
processDeferredPointer(internal.lastEvent.current, pointerId);
|
|
1534
|
+
}
|
|
1535
|
+
} else {
|
|
1536
|
+
flushDeferredPointers();
|
|
1537
|
+
if (internal.lastEvent?.current) {
|
|
1538
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
},
|
|
1542
|
+
flush: () => {
|
|
1543
|
+
const { events, internal } = store.getState();
|
|
1544
|
+
flushDeferredPointers();
|
|
1545
|
+
if (events.updateOnFrame && internal.lastEvent?.current && events.handlers) {
|
|
1546
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1547
|
+
}
|
|
1378
1548
|
},
|
|
1379
1549
|
connect: (target) => {
|
|
1550
|
+
if (!target) return;
|
|
1380
1551
|
const { set, events } = store.getState();
|
|
1381
1552
|
events.disconnect?.();
|
|
1382
1553
|
set((state) => ({ events: { ...state.events, connected: target } }));
|
|
@@ -1400,6 +1571,32 @@ function createPointerEvents(store) {
|
|
|
1400
1571
|
}
|
|
1401
1572
|
set((state) => ({ events: { ...state.events, connected: void 0 } }));
|
|
1402
1573
|
}
|
|
1574
|
+
},
|
|
1575
|
+
registerPointer: (config) => {
|
|
1576
|
+
const pointerId = nextXRPointerId++;
|
|
1577
|
+
xrPointers.set(pointerId, config);
|
|
1578
|
+
const { internal } = store.getState();
|
|
1579
|
+
getPointerState(internal, pointerId);
|
|
1580
|
+
return pointerId;
|
|
1581
|
+
},
|
|
1582
|
+
unregisterPointer: (pointerId) => {
|
|
1583
|
+
xrPointers.delete(pointerId);
|
|
1584
|
+
const { internal } = store.getState();
|
|
1585
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1586
|
+
if (pointerState) {
|
|
1587
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1588
|
+
const eventObject = hoveredObj.eventObject;
|
|
1589
|
+
const instance = eventObject.__r3f;
|
|
1590
|
+
if (instance?.eventCount) {
|
|
1591
|
+
const handlers = instance.handlers;
|
|
1592
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1593
|
+
handlers.onPointerOut?.(data);
|
|
1594
|
+
handlers.onPointerLeave?.(data);
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
internal.pointerMap.delete(pointerId);
|
|
1598
|
+
}
|
|
1599
|
+
internal.pointerDirty.delete(pointerId);
|
|
1403
1600
|
}
|
|
1404
1601
|
};
|
|
1405
1602
|
}
|
|
@@ -1713,7 +1910,7 @@ function shouldRun(job, now) {
|
|
|
1713
1910
|
const minInterval = 1e3 / job.fps;
|
|
1714
1911
|
const lastRun = job.lastRun ?? 0;
|
|
1715
1912
|
const elapsed = now - lastRun;
|
|
1716
|
-
if (elapsed < minInterval) return false;
|
|
1913
|
+
if (elapsed < minInterval - 1) return false;
|
|
1717
1914
|
if (job.drop) {
|
|
1718
1915
|
job.lastRun = now;
|
|
1719
1916
|
} else {
|
|
@@ -2530,7 +2727,14 @@ const createStore = (invalidate, advance) => {
|
|
|
2530
2727
|
frustum: new webgpu.Frustum(),
|
|
2531
2728
|
autoUpdateFrustum: true,
|
|
2532
2729
|
raycaster: null,
|
|
2533
|
-
events: {
|
|
2730
|
+
events: {
|
|
2731
|
+
priority: 1,
|
|
2732
|
+
enabled: true,
|
|
2733
|
+
connected: false,
|
|
2734
|
+
frameTimedRaycasts: true,
|
|
2735
|
+
alwaysFireOnScroll: true,
|
|
2736
|
+
updateOnFrame: false
|
|
2737
|
+
},
|
|
2534
2738
|
scene: null,
|
|
2535
2739
|
rootScene: null,
|
|
2536
2740
|
xr: null,
|
|
@@ -2621,11 +2825,13 @@ const createStore = (invalidate, advance) => {
|
|
|
2621
2825
|
},
|
|
2622
2826
|
setError: (error) => set(() => ({ error })),
|
|
2623
2827
|
error: null,
|
|
2624
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures,
|
|
2828
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
2625
2829
|
uniforms: {},
|
|
2626
2830
|
nodes: {},
|
|
2831
|
+
buffers: {},
|
|
2832
|
+
gpuStorage: {},
|
|
2627
2833
|
textures: /* @__PURE__ */ new Map(),
|
|
2628
|
-
|
|
2834
|
+
renderPipeline: null,
|
|
2629
2835
|
passes: {},
|
|
2630
2836
|
_hmrVersion: 0,
|
|
2631
2837
|
_sizeImperative: false,
|
|
@@ -2634,12 +2840,16 @@ const createStore = (invalidate, advance) => {
|
|
|
2634
2840
|
internal: {
|
|
2635
2841
|
// Events
|
|
2636
2842
|
interaction: [],
|
|
2637
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
2638
2843
|
subscribers: [],
|
|
2844
|
+
// Per-pointer state (new unified structure)
|
|
2845
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
2846
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
2847
|
+
lastEvent: React__namespace.createRef(),
|
|
2848
|
+
// Deprecated but kept for backwards compatibility
|
|
2849
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
2639
2850
|
initialClick: [0, 0],
|
|
2640
2851
|
initialHits: [],
|
|
2641
2852
|
capturedMap: /* @__PURE__ */ new Map(),
|
|
2642
|
-
lastEvent: React__namespace.createRef(),
|
|
2643
2853
|
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
2644
2854
|
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
2645
2855
|
// Occlusion system (WebGPU only)
|
|
@@ -2727,14 +2937,16 @@ const createStore = (invalidate, advance) => {
|
|
|
2727
2937
|
oldSize = size;
|
|
2728
2938
|
oldDpr = viewport.dpr;
|
|
2729
2939
|
updateCamera(camera, size);
|
|
2730
|
-
if (canvasTarget) {
|
|
2940
|
+
if (internal.isSecondary && canvasTarget) {
|
|
2731
2941
|
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2732
|
-
|
|
2733
|
-
canvasTarget.setSize(size.width, size.height, updateStyle);
|
|
2942
|
+
canvasTarget.setSize(size.width, size.height, false);
|
|
2734
2943
|
} else {
|
|
2735
2944
|
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
2736
|
-
|
|
2737
|
-
|
|
2945
|
+
actualRenderer.setSize(size.width, size.height, false);
|
|
2946
|
+
if (canvasTarget) {
|
|
2947
|
+
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2948
|
+
canvasTarget.setSize(size.width, size.height, false);
|
|
2949
|
+
}
|
|
2738
2950
|
}
|
|
2739
2951
|
}
|
|
2740
2952
|
if (camera !== oldCamera) {
|
|
@@ -15019,7 +15231,6 @@ function createRoot(canvas) {
|
|
|
15019
15231
|
events,
|
|
15020
15232
|
onCreated: onCreatedCallback,
|
|
15021
15233
|
shadows = false,
|
|
15022
|
-
textureColorSpace = webgpu.SRGBColorSpace,
|
|
15023
15234
|
orthographic = false,
|
|
15024
15235
|
frameloop = "always",
|
|
15025
15236
|
dpr = [1, 2],
|
|
@@ -15034,6 +15245,7 @@ function createRoot(canvas) {
|
|
|
15034
15245
|
_sizeProps,
|
|
15035
15246
|
forceEven
|
|
15036
15247
|
} = props;
|
|
15248
|
+
const textureColorSpace = is.obj(glConfig) && !is.fun(glConfig) && !isRenderer(glConfig) && glConfig.textureColorSpace || is.obj(rendererConfig) && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && rendererConfig.textureColorSpace || webgpu.SRGBColorSpace;
|
|
15037
15249
|
const state = store.getState();
|
|
15038
15250
|
const defaultGPUProps = {
|
|
15039
15251
|
canvas,
|
|
@@ -15071,6 +15283,12 @@ function createRoot(canvas) {
|
|
|
15071
15283
|
} else if (!state.internal.actualRenderer) {
|
|
15072
15284
|
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, webgpu.WebGPURenderer);
|
|
15073
15285
|
if (!renderer.hasInitialized?.()) {
|
|
15286
|
+
const size2 = computeInitialSize(canvas, propsSize);
|
|
15287
|
+
if (size2.width > 0 && size2.height > 0) {
|
|
15288
|
+
const pixelRatio = calculateDpr(dpr);
|
|
15289
|
+
canvas.width = size2.width * pixelRatio;
|
|
15290
|
+
canvas.height = size2.height * pixelRatio;
|
|
15291
|
+
}
|
|
15074
15292
|
await renderer.init();
|
|
15075
15293
|
}
|
|
15076
15294
|
const backend = renderer.backend;
|
|
@@ -15180,7 +15398,7 @@ function createRoot(canvas) {
|
|
|
15180
15398
|
lastConfiguredProps.performance = performance;
|
|
15181
15399
|
}
|
|
15182
15400
|
if (!state.xr) {
|
|
15183
|
-
const handleXRFrame = (timestamp,
|
|
15401
|
+
const handleXRFrame = (timestamp, _frame) => {
|
|
15184
15402
|
const state2 = store.getState();
|
|
15185
15403
|
if (state2.frameloop === "never") return;
|
|
15186
15404
|
advance(timestamp);
|
|
@@ -15216,15 +15434,22 @@ function createRoot(canvas) {
|
|
|
15216
15434
|
const oldType = renderer.shadowMap.type;
|
|
15217
15435
|
renderer.shadowMap.enabled = !!shadows;
|
|
15218
15436
|
if (is.boo(shadows)) {
|
|
15219
|
-
renderer.shadowMap.type = webgpu.
|
|
15437
|
+
renderer.shadowMap.type = webgpu.PCFShadowMap;
|
|
15220
15438
|
} else if (is.str(shadows)) {
|
|
15439
|
+
if (shadows === "soft") {
|
|
15440
|
+
notifyDepreciated({
|
|
15441
|
+
heading: 'shadows="soft" is deprecated',
|
|
15442
|
+
body: "Three has depreciated soft and improved basic PCFShadows, we converted for you.",
|
|
15443
|
+
link: "https://github.com/mrdoob/three.js/wiki/Migration-Guide?utm_source=chatgpt.com#181--182"
|
|
15444
|
+
});
|
|
15445
|
+
}
|
|
15221
15446
|
const types = {
|
|
15222
15447
|
basic: webgpu.BasicShadowMap,
|
|
15223
15448
|
percentage: webgpu.PCFShadowMap,
|
|
15224
|
-
soft: webgpu.
|
|
15449
|
+
soft: webgpu.PCFShadowMap,
|
|
15225
15450
|
variance: webgpu.VSMShadowMap
|
|
15226
15451
|
};
|
|
15227
|
-
renderer.shadowMap.type = types[shadows] ?? webgpu.
|
|
15452
|
+
renderer.shadowMap.type = types[shadows] ?? webgpu.PCFShadowMap;
|
|
15228
15453
|
} else if (is.obj(shadows)) {
|
|
15229
15454
|
Object.assign(renderer.shadowMap, shadows);
|
|
15230
15455
|
}
|
|
@@ -15240,13 +15465,24 @@ function createRoot(canvas) {
|
|
|
15240
15465
|
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
15241
15466
|
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
15242
15467
|
}
|
|
15468
|
+
const r3fProps = ["textureColorSpace"];
|
|
15469
|
+
const constructorOnlyProps = ["samples", "antialias", "alpha", "canvas", "powerPreference"];
|
|
15470
|
+
const nonApplyProps = [...r3fProps, ...constructorOnlyProps];
|
|
15243
15471
|
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
15244
|
-
|
|
15472
|
+
const glProps = {};
|
|
15473
|
+
for (const key in glConfig) {
|
|
15474
|
+
if (!nonApplyProps.includes(key)) glProps[key] = glConfig[key];
|
|
15475
|
+
}
|
|
15476
|
+
applyProps(renderer, glProps);
|
|
15245
15477
|
}
|
|
15246
15478
|
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
15247
15479
|
const currentRenderer = state.renderer;
|
|
15248
15480
|
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
15249
|
-
|
|
15481
|
+
const rendererProps = {};
|
|
15482
|
+
for (const key in rendererConfig) {
|
|
15483
|
+
if (!nonApplyProps.includes(key)) rendererProps[key] = rendererConfig[key];
|
|
15484
|
+
}
|
|
15485
|
+
applyProps(currentRenderer, rendererProps);
|
|
15250
15486
|
}
|
|
15251
15487
|
}
|
|
15252
15488
|
const scheduler = getScheduler();
|
|
@@ -15272,6 +15508,18 @@ function createRoot(canvas) {
|
|
|
15272
15508
|
system: true
|
|
15273
15509
|
}
|
|
15274
15510
|
);
|
|
15511
|
+
const unregisterEventsFlush = scheduler.register(
|
|
15512
|
+
() => {
|
|
15513
|
+
const state2 = store.getState();
|
|
15514
|
+
state2.events.flush?.();
|
|
15515
|
+
},
|
|
15516
|
+
{
|
|
15517
|
+
id: `${newRootId}_events`,
|
|
15518
|
+
rootId: newRootId,
|
|
15519
|
+
phase: "input",
|
|
15520
|
+
system: true
|
|
15521
|
+
}
|
|
15522
|
+
);
|
|
15275
15523
|
const unregisterFrustum = scheduler.register(
|
|
15276
15524
|
() => {
|
|
15277
15525
|
const state2 = store.getState();
|
|
@@ -15306,7 +15554,7 @@ function createRoot(canvas) {
|
|
|
15306
15554
|
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
15307
15555
|
if (userHandlesRender || state2.internal.priority) return;
|
|
15308
15556
|
try {
|
|
15309
|
-
if (state2.
|
|
15557
|
+
if (state2.renderPipeline?.render) state2.renderPipeline.render();
|
|
15310
15558
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
15311
15559
|
} catch (error) {
|
|
15312
15560
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -15331,6 +15579,7 @@ function createRoot(canvas) {
|
|
|
15331
15579
|
unregisterRoot: () => {
|
|
15332
15580
|
unregisterRoot();
|
|
15333
15581
|
unregisterCanvasTarget();
|
|
15582
|
+
unregisterEventsFlush();
|
|
15334
15583
|
unregisterFrustum();
|
|
15335
15584
|
unregisterVisibility();
|
|
15336
15585
|
unregisterRender();
|
|
@@ -15496,9 +15745,13 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
15496
15745
|
const store = traditional.createWithEqualityFn((set, get) => ({ ...rest, set, get }));
|
|
15497
15746
|
const onMutate = (prev) => store.setState((state2) => inject.current(prev, state2));
|
|
15498
15747
|
onMutate(previousRoot.getState());
|
|
15499
|
-
previousRoot.subscribe(onMutate);
|
|
15500
15748
|
return store;
|
|
15501
15749
|
}, [previousRoot, container]);
|
|
15750
|
+
useIsomorphicLayoutEffect(() => {
|
|
15751
|
+
const onMutate = (prev) => usePortalStore.setState((state2) => inject.current(prev, state2));
|
|
15752
|
+
const unsubscribe = previousRoot.subscribe(onMutate);
|
|
15753
|
+
return unsubscribe;
|
|
15754
|
+
}, [previousRoot, usePortalStore]);
|
|
15502
15755
|
return (
|
|
15503
15756
|
// @ts-ignore, reconciler types are not maintained
|
|
15504
15757
|
/* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reconciler.createPortal(
|
|
@@ -15543,8 +15796,18 @@ function CanvasImpl({
|
|
|
15543
15796
|
forceEven,
|
|
15544
15797
|
...props
|
|
15545
15798
|
}) {
|
|
15546
|
-
const
|
|
15547
|
-
|
|
15799
|
+
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
15800
|
+
let primaryCanvas;
|
|
15801
|
+
let scheduler;
|
|
15802
|
+
let renderer;
|
|
15803
|
+
if (isRendererConfig) {
|
|
15804
|
+
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
15805
|
+
primaryCanvas = pc;
|
|
15806
|
+
scheduler = sc;
|
|
15807
|
+
renderer = Object.keys(rest).length > 0 ? rest : rendererProp;
|
|
15808
|
+
} else {
|
|
15809
|
+
renderer = rendererProp;
|
|
15810
|
+
}
|
|
15548
15811
|
React__namespace.useMemo(() => extend(THREE), []);
|
|
15549
15812
|
const Bridge = useBridge();
|
|
15550
15813
|
const backgroundProps = React__namespace.useMemo(() => {
|
|
@@ -15719,6 +15982,7 @@ function CanvasImpl({
|
|
|
15719
15982
|
queueMicrotask(() => {
|
|
15720
15983
|
const rootEntry = _roots.get(canvas);
|
|
15721
15984
|
if (rootEntry?.store) {
|
|
15985
|
+
console.log("[R3F] HMR detected \u2014 rebuilding nodes/uniforms");
|
|
15722
15986
|
rootEntry.store.setState((state) => ({
|
|
15723
15987
|
nodes: {},
|
|
15724
15988
|
uniforms: {},
|
|
@@ -15730,8 +15994,7 @@ function CanvasImpl({
|
|
|
15730
15994
|
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
15731
15995
|
const hot = undefined;
|
|
15732
15996
|
hot.on("vite:afterUpdate", handleHMR);
|
|
15733
|
-
return () => hot.
|
|
15734
|
-
});
|
|
15997
|
+
return () => hot.off?.("vite:afterUpdate", handleHMR);
|
|
15735
15998
|
}
|
|
15736
15999
|
if (typeof module !== "undefined" && module.hot) {
|
|
15737
16000
|
const hot = module.hot;
|
|
@@ -15754,7 +16017,16 @@ function CanvasImpl({
|
|
|
15754
16017
|
...style
|
|
15755
16018
|
},
|
|
15756
16019
|
...props,
|
|
15757
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16020
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16021
|
+
"canvas",
|
|
16022
|
+
{
|
|
16023
|
+
ref: canvasRef,
|
|
16024
|
+
id,
|
|
16025
|
+
className: "r3f-canvas",
|
|
16026
|
+
style: { display: "block", width: "100%", height: "100%" },
|
|
16027
|
+
children: fallback
|
|
16028
|
+
}
|
|
16029
|
+
) })
|
|
15758
16030
|
}
|
|
15759
16031
|
);
|
|
15760
16032
|
}
|
|
@@ -15830,6 +16102,8 @@ function createScopedStore(data) {
|
|
|
15830
16102
|
function createLazyCreatorState(state) {
|
|
15831
16103
|
let _uniforms = null;
|
|
15832
16104
|
let _nodes = null;
|
|
16105
|
+
let _buffers = null;
|
|
16106
|
+
let _gpuStorage = null;
|
|
15833
16107
|
return Object.create(state, {
|
|
15834
16108
|
uniforms: {
|
|
15835
16109
|
get() {
|
|
@@ -15840,6 +16114,16 @@ function createLazyCreatorState(state) {
|
|
|
15840
16114
|
get() {
|
|
15841
16115
|
return _nodes ?? (_nodes = createScopedStore(state.nodes));
|
|
15842
16116
|
}
|
|
16117
|
+
},
|
|
16118
|
+
buffers: {
|
|
16119
|
+
get() {
|
|
16120
|
+
return _buffers ?? (_buffers = createScopedStore(state.buffers));
|
|
16121
|
+
}
|
|
16122
|
+
},
|
|
16123
|
+
gpuStorage: {
|
|
16124
|
+
get() {
|
|
16125
|
+
return _gpuStorage ?? (_gpuStorage = createScopedStore(state.gpuStorage));
|
|
16126
|
+
}
|
|
15843
16127
|
}
|
|
15844
16128
|
});
|
|
15845
16129
|
}
|
|
@@ -15922,6 +16206,10 @@ function vectorize(inObject) {
|
|
|
15922
16206
|
if (obj.isVector2 || obj.isVector3 || obj.isVector4) return inObject;
|
|
15923
16207
|
if (obj.isMatrix3 || obj.isMatrix4) return inObject;
|
|
15924
16208
|
if (obj.isColor || obj.isEuler || obj.isQuaternion || obj.isSpherical) return inObject;
|
|
16209
|
+
if ("r" in obj && "g" in obj && "b" in obj && typeof obj.r === "number" && typeof obj.g === "number" && typeof obj.b === "number") {
|
|
16210
|
+
const scale = obj.r > 1 || obj.g > 1 || obj.b > 1 ? 1 / 255 : 1;
|
|
16211
|
+
return new webgpu.Color(obj.r * scale, obj.g * scale, obj.b * scale);
|
|
16212
|
+
}
|
|
15925
16213
|
if ("x" in obj && "y" in obj && typeof obj.x === "number" && typeof obj.y === "number") {
|
|
15926
16214
|
if ("w" in obj && typeof obj.w === "number" && "z" in obj && typeof obj.z === "number") {
|
|
15927
16215
|
return new webgpu.Vector4(obj.x, obj.y, obj.z, obj.w);
|
|
@@ -16377,7 +16665,351 @@ function useLocalNodes(creator) {
|
|
|
16377
16665
|
}, [store, creator, uniforms, nodes, textures, hmrVersion]);
|
|
16378
16666
|
}
|
|
16379
16667
|
|
|
16380
|
-
|
|
16668
|
+
const isBufferLike = (value) => {
|
|
16669
|
+
if (value === null || typeof value !== "object") return false;
|
|
16670
|
+
if (ArrayBuffer.isView(value)) return true;
|
|
16671
|
+
if ("isBufferAttribute" in value) return true;
|
|
16672
|
+
if ("uuid" in value || "nodeType" in value) return true;
|
|
16673
|
+
return false;
|
|
16674
|
+
};
|
|
16675
|
+
const disposeBuffer = (buffer) => {
|
|
16676
|
+
if (buffer === null || typeof buffer !== "object") return;
|
|
16677
|
+
if ("dispose" in buffer && typeof buffer.dispose === "function") {
|
|
16678
|
+
buffer.dispose();
|
|
16679
|
+
}
|
|
16680
|
+
};
|
|
16681
|
+
function useBuffers(creatorOrScope, scope) {
|
|
16682
|
+
const store = useStore();
|
|
16683
|
+
const removeBuffers = React.useCallback(
|
|
16684
|
+
(names, targetScope) => {
|
|
16685
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16686
|
+
store.setState((state) => {
|
|
16687
|
+
if (targetScope) {
|
|
16688
|
+
const currentScope = { ...state.buffers[targetScope] };
|
|
16689
|
+
for (const name of nameArray) delete currentScope[name];
|
|
16690
|
+
return { buffers: { ...state.buffers, [targetScope]: currentScope } };
|
|
16691
|
+
}
|
|
16692
|
+
const buffers2 = { ...state.buffers };
|
|
16693
|
+
for (const name of nameArray) if (isBufferLike(buffers2[name])) delete buffers2[name];
|
|
16694
|
+
return { buffers: buffers2 };
|
|
16695
|
+
});
|
|
16696
|
+
},
|
|
16697
|
+
[store]
|
|
16698
|
+
);
|
|
16699
|
+
const clearBuffers = React.useCallback(
|
|
16700
|
+
(targetScope) => {
|
|
16701
|
+
store.setState((state) => {
|
|
16702
|
+
if (targetScope && targetScope !== "root") {
|
|
16703
|
+
const { [targetScope]: _, ...rest } = state.buffers;
|
|
16704
|
+
return { buffers: rest };
|
|
16705
|
+
}
|
|
16706
|
+
if (targetScope === "root") {
|
|
16707
|
+
const buffers2 = {};
|
|
16708
|
+
for (const [key, value] of Object.entries(state.buffers)) {
|
|
16709
|
+
if (!isBufferLike(value)) buffers2[key] = value;
|
|
16710
|
+
}
|
|
16711
|
+
return { buffers: buffers2 };
|
|
16712
|
+
}
|
|
16713
|
+
return { buffers: {} };
|
|
16714
|
+
});
|
|
16715
|
+
},
|
|
16716
|
+
[store]
|
|
16717
|
+
);
|
|
16718
|
+
const rebuildBuffers = React.useCallback(
|
|
16719
|
+
(targetScope) => {
|
|
16720
|
+
store.setState((state) => {
|
|
16721
|
+
let newBuffers = state.buffers;
|
|
16722
|
+
if (targetScope && targetScope !== "root") {
|
|
16723
|
+
const { [targetScope]: _, ...rest } = state.buffers;
|
|
16724
|
+
newBuffers = rest;
|
|
16725
|
+
} else if (targetScope === "root") {
|
|
16726
|
+
newBuffers = {};
|
|
16727
|
+
for (const [key, value] of Object.entries(state.buffers)) {
|
|
16728
|
+
if (!isBufferLike(value)) newBuffers[key] = value;
|
|
16729
|
+
}
|
|
16730
|
+
} else {
|
|
16731
|
+
newBuffers = {};
|
|
16732
|
+
}
|
|
16733
|
+
return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
|
|
16734
|
+
});
|
|
16735
|
+
},
|
|
16736
|
+
[store]
|
|
16737
|
+
);
|
|
16738
|
+
const disposeBuffers = React.useCallback(
|
|
16739
|
+
(names, targetScope) => {
|
|
16740
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16741
|
+
const state = store.getState();
|
|
16742
|
+
for (const name of nameArray) {
|
|
16743
|
+
const buffer = targetScope ? state.buffers[targetScope]?.[name] : state.buffers[name];
|
|
16744
|
+
if (buffer && isBufferLike(buffer)) {
|
|
16745
|
+
disposeBuffer(buffer);
|
|
16746
|
+
}
|
|
16747
|
+
}
|
|
16748
|
+
removeBuffers(names, targetScope);
|
|
16749
|
+
},
|
|
16750
|
+
[store, removeBuffers]
|
|
16751
|
+
);
|
|
16752
|
+
const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
|
|
16753
|
+
const storeBuffers = useThree((s) => s.buffers);
|
|
16754
|
+
const hmrVersion = useThree((s) => s._hmrVersion);
|
|
16755
|
+
const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
|
|
16756
|
+
const readerDep = isReader ? storeBuffers : null;
|
|
16757
|
+
const creatorDep = isReader ? null : hmrVersion;
|
|
16758
|
+
const buffers = React.useMemo(() => {
|
|
16759
|
+
if (creatorOrScope === void 0) {
|
|
16760
|
+
return storeBuffers;
|
|
16761
|
+
}
|
|
16762
|
+
if (typeof creatorOrScope === "string") {
|
|
16763
|
+
const scopeData = storeBuffers[creatorOrScope];
|
|
16764
|
+
if (scopeData && !isBufferLike(scopeData)) return scopeData;
|
|
16765
|
+
return {};
|
|
16766
|
+
}
|
|
16767
|
+
const state = store.getState();
|
|
16768
|
+
const set = store.setState;
|
|
16769
|
+
const creator = creatorOrScope;
|
|
16770
|
+
const wrappedState = createLazyCreatorState(state);
|
|
16771
|
+
const created = creator(wrappedState);
|
|
16772
|
+
const result = {};
|
|
16773
|
+
let hasNewBuffers = false;
|
|
16774
|
+
if (scope) {
|
|
16775
|
+
const currentScope = state.buffers[scope] ?? {};
|
|
16776
|
+
for (const [name, buffer] of Object.entries(created)) {
|
|
16777
|
+
if (currentScope[name]) {
|
|
16778
|
+
result[name] = currentScope[name];
|
|
16779
|
+
} else {
|
|
16780
|
+
if ("setName" in buffer && typeof buffer.setName === "function") {
|
|
16781
|
+
buffer.setName(`${scope}.${name}`);
|
|
16782
|
+
}
|
|
16783
|
+
result[name] = buffer;
|
|
16784
|
+
hasNewBuffers = true;
|
|
16785
|
+
}
|
|
16786
|
+
}
|
|
16787
|
+
if (hasNewBuffers) {
|
|
16788
|
+
set((s) => ({
|
|
16789
|
+
buffers: {
|
|
16790
|
+
...s.buffers,
|
|
16791
|
+
[scope]: { ...s.buffers[scope], ...result }
|
|
16792
|
+
}
|
|
16793
|
+
}));
|
|
16794
|
+
}
|
|
16795
|
+
return result;
|
|
16796
|
+
}
|
|
16797
|
+
for (const [name, buffer] of Object.entries(created)) {
|
|
16798
|
+
const existing = state.buffers[name];
|
|
16799
|
+
if (existing && isBufferLike(existing)) {
|
|
16800
|
+
result[name] = existing;
|
|
16801
|
+
} else {
|
|
16802
|
+
if ("setName" in buffer && typeof buffer.setName === "function") {
|
|
16803
|
+
buffer.setName(name);
|
|
16804
|
+
}
|
|
16805
|
+
result[name] = buffer;
|
|
16806
|
+
hasNewBuffers = true;
|
|
16807
|
+
}
|
|
16808
|
+
}
|
|
16809
|
+
if (hasNewBuffers) {
|
|
16810
|
+
set((s) => ({ buffers: { ...s.buffers, ...result } }));
|
|
16811
|
+
}
|
|
16812
|
+
return result;
|
|
16813
|
+
}, [store, scopeDep, readerDep, creatorDep]);
|
|
16814
|
+
return { ...buffers, removeBuffers, clearBuffers, rebuildBuffers, disposeBuffers };
|
|
16815
|
+
}
|
|
16816
|
+
function rebuildAllBuffers(store, scope) {
|
|
16817
|
+
store.setState((state) => {
|
|
16818
|
+
let newBuffers = state.buffers;
|
|
16819
|
+
if (scope && scope !== "root") {
|
|
16820
|
+
const { [scope]: _, ...rest } = state.buffers;
|
|
16821
|
+
newBuffers = rest;
|
|
16822
|
+
} else if (scope === "root") {
|
|
16823
|
+
newBuffers = {};
|
|
16824
|
+
for (const [key, value] of Object.entries(state.buffers)) {
|
|
16825
|
+
if (!isBufferLike(value)) newBuffers[key] = value;
|
|
16826
|
+
}
|
|
16827
|
+
} else {
|
|
16828
|
+
newBuffers = {};
|
|
16829
|
+
}
|
|
16830
|
+
return { buffers: newBuffers, _hmrVersion: state._hmrVersion + 1 };
|
|
16831
|
+
});
|
|
16832
|
+
}
|
|
16833
|
+
|
|
16834
|
+
const isStorageLike = (value) => {
|
|
16835
|
+
if (value === null || typeof value !== "object") return false;
|
|
16836
|
+
if ("isTexture" in value) return true;
|
|
16837
|
+
if ("isData3DTexture" in value) return true;
|
|
16838
|
+
if ("uuid" in value || "nodeType" in value) return true;
|
|
16839
|
+
return false;
|
|
16840
|
+
};
|
|
16841
|
+
const disposeStorage = (storage) => {
|
|
16842
|
+
if (storage === null || typeof storage !== "object") return;
|
|
16843
|
+
if ("dispose" in storage && typeof storage.dispose === "function") {
|
|
16844
|
+
storage.dispose();
|
|
16845
|
+
}
|
|
16846
|
+
};
|
|
16847
|
+
function useGPUStorage(creatorOrScope, scope) {
|
|
16848
|
+
const store = useStore();
|
|
16849
|
+
const removeStorage = React.useCallback(
|
|
16850
|
+
(names, targetScope) => {
|
|
16851
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16852
|
+
store.setState((state) => {
|
|
16853
|
+
if (targetScope) {
|
|
16854
|
+
const currentScope = { ...state.gpuStorage[targetScope] };
|
|
16855
|
+
for (const name of nameArray) delete currentScope[name];
|
|
16856
|
+
return { gpuStorage: { ...state.gpuStorage, [targetScope]: currentScope } };
|
|
16857
|
+
}
|
|
16858
|
+
const gpuStorage2 = { ...state.gpuStorage };
|
|
16859
|
+
for (const name of nameArray) if (isStorageLike(gpuStorage2[name])) delete gpuStorage2[name];
|
|
16860
|
+
return { gpuStorage: gpuStorage2 };
|
|
16861
|
+
});
|
|
16862
|
+
},
|
|
16863
|
+
[store]
|
|
16864
|
+
);
|
|
16865
|
+
const clearStorage = React.useCallback(
|
|
16866
|
+
(targetScope) => {
|
|
16867
|
+
store.setState((state) => {
|
|
16868
|
+
if (targetScope && targetScope !== "root") {
|
|
16869
|
+
const { [targetScope]: _, ...rest } = state.gpuStorage;
|
|
16870
|
+
return { gpuStorage: rest };
|
|
16871
|
+
}
|
|
16872
|
+
if (targetScope === "root") {
|
|
16873
|
+
const gpuStorage2 = {};
|
|
16874
|
+
for (const [key, value] of Object.entries(state.gpuStorage)) {
|
|
16875
|
+
if (!isStorageLike(value)) gpuStorage2[key] = value;
|
|
16876
|
+
}
|
|
16877
|
+
return { gpuStorage: gpuStorage2 };
|
|
16878
|
+
}
|
|
16879
|
+
return { gpuStorage: {} };
|
|
16880
|
+
});
|
|
16881
|
+
},
|
|
16882
|
+
[store]
|
|
16883
|
+
);
|
|
16884
|
+
const rebuildStorage = React.useCallback(
|
|
16885
|
+
(targetScope) => {
|
|
16886
|
+
store.setState((state) => {
|
|
16887
|
+
let newStorage = state.gpuStorage;
|
|
16888
|
+
if (targetScope && targetScope !== "root") {
|
|
16889
|
+
const { [targetScope]: _, ...rest } = state.gpuStorage;
|
|
16890
|
+
newStorage = rest;
|
|
16891
|
+
} else if (targetScope === "root") {
|
|
16892
|
+
newStorage = {};
|
|
16893
|
+
for (const [key, value] of Object.entries(state.gpuStorage)) {
|
|
16894
|
+
if (!isStorageLike(value)) newStorage[key] = value;
|
|
16895
|
+
}
|
|
16896
|
+
} else {
|
|
16897
|
+
newStorage = {};
|
|
16898
|
+
}
|
|
16899
|
+
return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
|
|
16900
|
+
});
|
|
16901
|
+
},
|
|
16902
|
+
[store]
|
|
16903
|
+
);
|
|
16904
|
+
const disposeStorageFn = React.useCallback(
|
|
16905
|
+
(names, targetScope) => {
|
|
16906
|
+
const nameArray = Array.isArray(names) ? names : [names];
|
|
16907
|
+
const state = store.getState();
|
|
16908
|
+
for (const name of nameArray) {
|
|
16909
|
+
const storage = targetScope ? state.gpuStorage[targetScope]?.[name] : state.gpuStorage[name];
|
|
16910
|
+
if (storage && isStorageLike(storage)) {
|
|
16911
|
+
disposeStorage(storage);
|
|
16912
|
+
}
|
|
16913
|
+
}
|
|
16914
|
+
removeStorage(names, targetScope);
|
|
16915
|
+
},
|
|
16916
|
+
[store, removeStorage]
|
|
16917
|
+
);
|
|
16918
|
+
const isReader = creatorOrScope === void 0 || typeof creatorOrScope === "string";
|
|
16919
|
+
const storeStorage = useThree((s) => s.gpuStorage);
|
|
16920
|
+
const hmrVersion = useThree((s) => s._hmrVersion);
|
|
16921
|
+
const scopeDep = typeof creatorOrScope === "string" ? creatorOrScope : scope;
|
|
16922
|
+
const readerDep = isReader ? storeStorage : null;
|
|
16923
|
+
const creatorDep = isReader ? null : hmrVersion;
|
|
16924
|
+
const gpuStorage = React.useMemo(() => {
|
|
16925
|
+
if (creatorOrScope === void 0) {
|
|
16926
|
+
return storeStorage;
|
|
16927
|
+
}
|
|
16928
|
+
if (typeof creatorOrScope === "string") {
|
|
16929
|
+
const scopeData = storeStorage[creatorOrScope];
|
|
16930
|
+
if (scopeData && !isStorageLike(scopeData)) return scopeData;
|
|
16931
|
+
return {};
|
|
16932
|
+
}
|
|
16933
|
+
const state = store.getState();
|
|
16934
|
+
const set = store.setState;
|
|
16935
|
+
const creator = creatorOrScope;
|
|
16936
|
+
const wrappedState = createLazyCreatorState(state);
|
|
16937
|
+
const created = creator(wrappedState);
|
|
16938
|
+
const result = {};
|
|
16939
|
+
let hasNewStorage = false;
|
|
16940
|
+
if (scope) {
|
|
16941
|
+
const currentScope = state.gpuStorage[scope] ?? {};
|
|
16942
|
+
for (const [name, storage] of Object.entries(created)) {
|
|
16943
|
+
if (currentScope[name]) {
|
|
16944
|
+
result[name] = currentScope[name];
|
|
16945
|
+
} else {
|
|
16946
|
+
if ("setName" in storage && typeof storage.setName === "function") {
|
|
16947
|
+
storage.setName(`${scope}.${name}`);
|
|
16948
|
+
}
|
|
16949
|
+
if ("name" in storage && typeof storage.name === "string") {
|
|
16950
|
+
storage.name = `${scope}.${name}`;
|
|
16951
|
+
}
|
|
16952
|
+
result[name] = storage;
|
|
16953
|
+
hasNewStorage = true;
|
|
16954
|
+
}
|
|
16955
|
+
}
|
|
16956
|
+
if (hasNewStorage) {
|
|
16957
|
+
set((s) => ({
|
|
16958
|
+
gpuStorage: {
|
|
16959
|
+
...s.gpuStorage,
|
|
16960
|
+
[scope]: { ...s.gpuStorage[scope], ...result }
|
|
16961
|
+
}
|
|
16962
|
+
}));
|
|
16963
|
+
}
|
|
16964
|
+
return result;
|
|
16965
|
+
}
|
|
16966
|
+
for (const [name, storage] of Object.entries(created)) {
|
|
16967
|
+
const existing = state.gpuStorage[name];
|
|
16968
|
+
if (existing && isStorageLike(existing)) {
|
|
16969
|
+
result[name] = existing;
|
|
16970
|
+
} else {
|
|
16971
|
+
if ("setName" in storage && typeof storage.setName === "function") {
|
|
16972
|
+
storage.setName(name);
|
|
16973
|
+
}
|
|
16974
|
+
if ("name" in storage && typeof storage.name === "string") {
|
|
16975
|
+
storage.name = name;
|
|
16976
|
+
}
|
|
16977
|
+
result[name] = storage;
|
|
16978
|
+
hasNewStorage = true;
|
|
16979
|
+
}
|
|
16980
|
+
}
|
|
16981
|
+
if (hasNewStorage) {
|
|
16982
|
+
set((s) => ({ gpuStorage: { ...s.gpuStorage, ...result } }));
|
|
16983
|
+
}
|
|
16984
|
+
return result;
|
|
16985
|
+
}, [store, scopeDep, readerDep, creatorDep]);
|
|
16986
|
+
return {
|
|
16987
|
+
...gpuStorage,
|
|
16988
|
+
removeStorage,
|
|
16989
|
+
clearStorage,
|
|
16990
|
+
rebuildStorage,
|
|
16991
|
+
disposeStorage: disposeStorageFn
|
|
16992
|
+
};
|
|
16993
|
+
}
|
|
16994
|
+
function rebuildAllStorage(store, scope) {
|
|
16995
|
+
store.setState((state) => {
|
|
16996
|
+
let newStorage = state.gpuStorage;
|
|
16997
|
+
if (scope && scope !== "root") {
|
|
16998
|
+
const { [scope]: _, ...rest } = state.gpuStorage;
|
|
16999
|
+
newStorage = rest;
|
|
17000
|
+
} else if (scope === "root") {
|
|
17001
|
+
newStorage = {};
|
|
17002
|
+
for (const [key, value] of Object.entries(state.gpuStorage)) {
|
|
17003
|
+
if (!isStorageLike(value)) newStorage[key] = value;
|
|
17004
|
+
}
|
|
17005
|
+
} else {
|
|
17006
|
+
newStorage = {};
|
|
17007
|
+
}
|
|
17008
|
+
return { gpuStorage: newStorage, _hmrVersion: state._hmrVersion + 1 };
|
|
17009
|
+
});
|
|
17010
|
+
}
|
|
17011
|
+
|
|
17012
|
+
function useRenderPipeline(mainCB, setupCB) {
|
|
16381
17013
|
const store = useStore();
|
|
16382
17014
|
const { scene, camera, renderer, isLegacy } = useThree();
|
|
16383
17015
|
const callbacksRanRef = React.useRef(false);
|
|
@@ -16396,7 +17028,7 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16396
17028
|
}, [store]);
|
|
16397
17029
|
const reset = React.useCallback(() => {
|
|
16398
17030
|
store.setState({
|
|
16399
|
-
|
|
17031
|
+
renderPipeline: null,
|
|
16400
17032
|
passes: {}
|
|
16401
17033
|
});
|
|
16402
17034
|
callbacksRanRef.current = false;
|
|
@@ -16409,13 +17041,13 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16409
17041
|
}, []);
|
|
16410
17042
|
React.useLayoutEffect(() => {
|
|
16411
17043
|
if (isLegacy) {
|
|
16412
|
-
throw new Error("
|
|
17044
|
+
throw new Error("useRenderPipeline is only available with WebGPU renderer. Set renderer prop on Canvas.");
|
|
16413
17045
|
}
|
|
16414
17046
|
if (!renderer || !scene || !camera) return;
|
|
16415
17047
|
const state = store.getState();
|
|
16416
17048
|
const set = store.setState;
|
|
16417
17049
|
try {
|
|
16418
|
-
let pp = state.
|
|
17050
|
+
let pp = state.renderPipeline;
|
|
16419
17051
|
let currentPasses = { ...state.passes };
|
|
16420
17052
|
let justCreatedPP = false;
|
|
16421
17053
|
if (!pp) {
|
|
@@ -16432,7 +17064,7 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16432
17064
|
}
|
|
16433
17065
|
currentPasses.scenePass = scenePass;
|
|
16434
17066
|
if (!pp.outputNode || justCreatedPP) pp.outputNode = scenePass;
|
|
16435
|
-
set({
|
|
17067
|
+
set({ renderPipeline: pp, passes: currentPasses });
|
|
16436
17068
|
const shouldRunCallbacks = justCreatedPP || !callbacksRanRef.current || !cacheValid;
|
|
16437
17069
|
if (shouldRunCallbacks) {
|
|
16438
17070
|
if (setupCBRef.current) {
|
|
@@ -16454,19 +17086,19 @@ function usePostProcessing(mainCB, setupCB) {
|
|
|
16454
17086
|
callbacksRanRef.current = true;
|
|
16455
17087
|
}
|
|
16456
17088
|
} catch (error) {
|
|
16457
|
-
console.error("[
|
|
17089
|
+
console.error("[useRenderPipeline] Setup error:", error);
|
|
16458
17090
|
}
|
|
16459
17091
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16460
17092
|
const passes = useThree((s) => s.passes);
|
|
16461
|
-
const
|
|
17093
|
+
const renderPipeline = useThree((s) => s.renderPipeline);
|
|
16462
17094
|
return {
|
|
16463
17095
|
passes,
|
|
16464
|
-
|
|
17096
|
+
renderPipeline,
|
|
16465
17097
|
clearPasses,
|
|
16466
17098
|
reset,
|
|
16467
17099
|
rebuild,
|
|
16468
|
-
// isReady indicates if
|
|
16469
|
-
isReady:
|
|
17100
|
+
// isReady indicates if RenderPipeline is configured and ready for rendering
|
|
17101
|
+
isReady: renderPipeline !== null
|
|
16470
17102
|
};
|
|
16471
17103
|
}
|
|
16472
17104
|
|
|
@@ -16543,7 +17175,9 @@ exports.isVectorLike = isVectorLike;
|
|
|
16543
17175
|
exports.once = once;
|
|
16544
17176
|
exports.prepare = prepare;
|
|
16545
17177
|
exports.presetsObj = presetsObj;
|
|
17178
|
+
exports.rebuildAllBuffers = rebuildAllBuffers;
|
|
16546
17179
|
exports.rebuildAllNodes = rebuildAllNodes;
|
|
17180
|
+
exports.rebuildAllStorage = rebuildAllStorage;
|
|
16547
17181
|
exports.rebuildAllUniforms = rebuildAllUniforms;
|
|
16548
17182
|
exports.reconciler = reconciler;
|
|
16549
17183
|
exports.registerPrimary = registerPrimary;
|
|
@@ -16556,8 +17190,10 @@ exports.unregisterPrimary = unregisterPrimary;
|
|
|
16556
17190
|
exports.updateCamera = updateCamera;
|
|
16557
17191
|
exports.updateFrustum = updateFrustum;
|
|
16558
17192
|
exports.useBridge = useBridge;
|
|
17193
|
+
exports.useBuffers = useBuffers;
|
|
16559
17194
|
exports.useEnvironment = useEnvironment;
|
|
16560
17195
|
exports.useFrame = useFrame;
|
|
17196
|
+
exports.useGPUStorage = useGPUStorage;
|
|
16561
17197
|
exports.useGraph = useGraph;
|
|
16562
17198
|
exports.useInstanceHandle = useInstanceHandle;
|
|
16563
17199
|
exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
|
|
@@ -16565,7 +17201,7 @@ exports.useLoader = useLoader;
|
|
|
16565
17201
|
exports.useLocalNodes = useLocalNodes;
|
|
16566
17202
|
exports.useMutableCallback = useMutableCallback;
|
|
16567
17203
|
exports.useNodes = useNodes;
|
|
16568
|
-
exports.
|
|
17204
|
+
exports.useRenderPipeline = useRenderPipeline;
|
|
16569
17205
|
exports.useRenderTarget = useRenderTarget;
|
|
16570
17206
|
exports.useStore = useStore;
|
|
16571
17207
|
exports.useTexture = useTexture;
|