@react-three/fiber 10.0.0-canary.604355a → 10.0.0-canary.aecbafb
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 +290 -73
- package/dist/index.d.cts +138 -21
- package/dist/index.d.mts +138 -21
- package/dist/index.d.ts +138 -21
- package/dist/index.mjs +290 -73
- package/dist/legacy.cjs +284 -73
- package/dist/legacy.d.cts +138 -21
- package/dist/legacy.d.mts +138 -21
- package/dist/legacy.d.ts +138 -21
- package/dist/legacy.mjs +284 -73
- package/dist/webgpu/index.cjs +665 -84
- package/dist/webgpu/index.d.cts +223 -34
- package/dist/webgpu/index.d.mts +223 -34
- package/dist/webgpu/index.d.ts +223 -34
- package/dist/webgpu/index.mjs +661 -84
- package/package.json +1 -1
package/dist/legacy.cjs
CHANGED
|
@@ -1005,6 +1005,9 @@ function applyProps(object, props) {
|
|
|
1005
1005
|
else target.set(value);
|
|
1006
1006
|
} else {
|
|
1007
1007
|
root[key] = value;
|
|
1008
|
+
if (key.endsWith("Node") && root.isMaterial) {
|
|
1009
|
+
root.needsUpdate = true;
|
|
1010
|
+
}
|
|
1008
1011
|
if (rootState && rootState.renderer?.outputColorSpace === three.SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
1009
1012
|
root[key].format === three.RGBAFormat && root[key].type === three.UnsignedByteType) {
|
|
1010
1013
|
root[key].colorSpace = rootState.textureColorSpace;
|
|
@@ -1038,38 +1041,60 @@ function applyProps(object, props) {
|
|
|
1038
1041
|
return object;
|
|
1039
1042
|
}
|
|
1040
1043
|
|
|
1044
|
+
const DEFAULT_POINTER_ID = 0;
|
|
1045
|
+
const XR_POINTER_ID_START = 1e3;
|
|
1046
|
+
function getPointerState(internal, pointerId) {
|
|
1047
|
+
let state = internal.pointerMap.get(pointerId);
|
|
1048
|
+
if (!state) {
|
|
1049
|
+
state = {
|
|
1050
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
1051
|
+
captured: /* @__PURE__ */ new Map(),
|
|
1052
|
+
initialClick: [0, 0],
|
|
1053
|
+
initialHits: []
|
|
1054
|
+
};
|
|
1055
|
+
internal.pointerMap.set(pointerId, state);
|
|
1056
|
+
}
|
|
1057
|
+
return state;
|
|
1058
|
+
}
|
|
1059
|
+
function getPointerId(event) {
|
|
1060
|
+
return "pointerId" in event ? event.pointerId : DEFAULT_POINTER_ID;
|
|
1061
|
+
}
|
|
1041
1062
|
function makeId(event) {
|
|
1042
1063
|
return (event.eventObject || event.object).uuid + "/" + event.index + event.instanceId;
|
|
1043
1064
|
}
|
|
1044
|
-
function releaseInternalPointerCapture(
|
|
1045
|
-
const
|
|
1065
|
+
function releaseInternalPointerCapture(internal, obj, pointerId) {
|
|
1066
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1067
|
+
if (!pointerState) return;
|
|
1068
|
+
const captureData = pointerState.captured.get(obj);
|
|
1046
1069
|
if (captureData) {
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
capturedMap.delete(pointerId);
|
|
1050
|
-
captureData.target.releasePointerCapture(pointerId);
|
|
1051
|
-
}
|
|
1070
|
+
pointerState.captured.delete(obj);
|
|
1071
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
1052
1072
|
}
|
|
1053
1073
|
}
|
|
1054
1074
|
function removeInteractivity(store, object) {
|
|
1055
1075
|
const { internal } = store.getState();
|
|
1056
1076
|
internal.interaction = internal.interaction.filter((o) => o !== object);
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1077
|
+
for (const [pointerId, pointerState] of internal.pointerMap) {
|
|
1078
|
+
pointerState.initialHits = pointerState.initialHits.filter((o) => o !== object);
|
|
1079
|
+
pointerState.hovered.forEach((value, key) => {
|
|
1080
|
+
if (value.eventObject === object || value.object === object) {
|
|
1081
|
+
pointerState.hovered.delete(key);
|
|
1082
|
+
}
|
|
1083
|
+
});
|
|
1084
|
+
if (pointerState.captured.has(object)) {
|
|
1085
|
+
releaseInternalPointerCapture(internal, object, pointerId);
|
|
1061
1086
|
}
|
|
1062
|
-
}
|
|
1063
|
-
internal.capturedMap.forEach((captures, pointerId) => {
|
|
1064
|
-
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
1065
|
-
});
|
|
1087
|
+
}
|
|
1066
1088
|
unregisterVisibility(store, object);
|
|
1067
1089
|
}
|
|
1068
1090
|
function createEvents(store) {
|
|
1069
|
-
function calculateDistance(event) {
|
|
1091
|
+
function calculateDistance(event, pointerId) {
|
|
1070
1092
|
const { internal } = store.getState();
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1093
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1094
|
+
if (!pointerState) return 0;
|
|
1095
|
+
const [initialX, initialY] = pointerState.initialClick;
|
|
1096
|
+
const dx = event.offsetX - initialX;
|
|
1097
|
+
const dy = event.offsetY - initialY;
|
|
1073
1098
|
return Math.round(Math.sqrt(dx * dx + dy * dy));
|
|
1074
1099
|
}
|
|
1075
1100
|
function filterPointerEvents(objects) {
|
|
@@ -1105,6 +1130,15 @@ function createEvents(store) {
|
|
|
1105
1130
|
return state2.raycaster.camera ? state2.raycaster.intersectObject(obj, true) : [];
|
|
1106
1131
|
}
|
|
1107
1132
|
let hits = eventsObjects.flatMap(handleRaycast).sort((a, b) => {
|
|
1133
|
+
const aInteractivePriority = a.object.userData?.interactivePriority;
|
|
1134
|
+
const bInteractivePriority = b.object.userData?.interactivePriority;
|
|
1135
|
+
if (aInteractivePriority !== void 0 || bInteractivePriority !== void 0) {
|
|
1136
|
+
if (aInteractivePriority !== void 0 && bInteractivePriority === void 0) return -1;
|
|
1137
|
+
if (bInteractivePriority !== void 0 && aInteractivePriority === void 0) return 1;
|
|
1138
|
+
if (aInteractivePriority !== bInteractivePriority) {
|
|
1139
|
+
return (bInteractivePriority ?? 0) - (aInteractivePriority ?? 0);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1108
1142
|
const aState = getRootState(a.object);
|
|
1109
1143
|
const bState = getRootState(b.object);
|
|
1110
1144
|
const aPriority = aState?.events?.priority ?? 1;
|
|
@@ -1126,9 +1160,13 @@ function createEvents(store) {
|
|
|
1126
1160
|
eventObject = eventObject.parent;
|
|
1127
1161
|
}
|
|
1128
1162
|
}
|
|
1129
|
-
if ("pointerId" in event
|
|
1130
|
-
|
|
1131
|
-
|
|
1163
|
+
if ("pointerId" in event) {
|
|
1164
|
+
const pointerId = event.pointerId;
|
|
1165
|
+
const pointerState = state.internal.pointerMap.get(pointerId);
|
|
1166
|
+
if (pointerState?.captured.size) {
|
|
1167
|
+
for (const captureData of pointerState.captured.values()) {
|
|
1168
|
+
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
1169
|
+
}
|
|
1132
1170
|
}
|
|
1133
1171
|
}
|
|
1134
1172
|
return intersections;
|
|
@@ -1141,27 +1179,25 @@ function createEvents(store) {
|
|
|
1141
1179
|
if (state) {
|
|
1142
1180
|
const { raycaster, pointer, camera, internal } = state;
|
|
1143
1181
|
const unprojectedPoint = new three.Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
1144
|
-
const hasPointerCapture = (id) =>
|
|
1182
|
+
const hasPointerCapture = (id) => {
|
|
1183
|
+
const pointerState = internal.pointerMap.get(id);
|
|
1184
|
+
return pointerState?.captured.has(hit.eventObject) ?? false;
|
|
1185
|
+
};
|
|
1145
1186
|
const setPointerCapture = (id) => {
|
|
1146
1187
|
const captureData = { intersection: hit, target: event.target };
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
} else {
|
|
1150
|
-
internal.capturedMap.set(id, /* @__PURE__ */ new Map([[hit.eventObject, captureData]]));
|
|
1151
|
-
}
|
|
1188
|
+
const pointerState = getPointerState(internal, id);
|
|
1189
|
+
pointerState.captured.set(hit.eventObject, captureData);
|
|
1152
1190
|
event.target.setPointerCapture(id);
|
|
1153
1191
|
};
|
|
1154
1192
|
const releasePointerCapture = (id) => {
|
|
1155
|
-
|
|
1156
|
-
if (captures) {
|
|
1157
|
-
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
1158
|
-
}
|
|
1193
|
+
releaseInternalPointerCapture(internal, hit.eventObject, id);
|
|
1159
1194
|
};
|
|
1160
1195
|
const extractEventProps = {};
|
|
1161
1196
|
for (const prop in event) {
|
|
1162
1197
|
const property = event[prop];
|
|
1163
1198
|
if (typeof property !== "function") extractEventProps[prop] = property;
|
|
1164
1199
|
}
|
|
1200
|
+
const eventPointerId = "pointerId" in event ? event.pointerId : void 0;
|
|
1165
1201
|
const raycastEvent = {
|
|
1166
1202
|
...hit,
|
|
1167
1203
|
...extractEventProps,
|
|
@@ -1172,18 +1208,19 @@ function createEvents(store) {
|
|
|
1172
1208
|
unprojectedPoint,
|
|
1173
1209
|
ray: raycaster.ray,
|
|
1174
1210
|
camera,
|
|
1211
|
+
pointerId: eventPointerId,
|
|
1175
1212
|
// Hijack stopPropagation, which just sets a flag
|
|
1176
1213
|
stopPropagation() {
|
|
1177
|
-
const
|
|
1214
|
+
const pointerState = eventPointerId !== void 0 ? internal.pointerMap.get(eventPointerId) : void 0;
|
|
1178
1215
|
if (
|
|
1179
1216
|
// ...if this pointer hasn't been captured
|
|
1180
|
-
!
|
|
1181
|
-
|
|
1217
|
+
!pointerState?.captured.size || // ... or if the hit object is capturing the pointer
|
|
1218
|
+
pointerState.captured.has(hit.eventObject)
|
|
1182
1219
|
) {
|
|
1183
1220
|
raycastEvent.stopped = localState.stopped = true;
|
|
1184
|
-
if (
|
|
1221
|
+
if (pointerState?.hovered.size && Array.from(pointerState.hovered.values()).find((i) => i.eventObject === hit.eventObject)) {
|
|
1185
1222
|
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
1186
|
-
cancelPointer([...higher, hit]);
|
|
1223
|
+
cancelPointer([...higher, hit], eventPointerId);
|
|
1187
1224
|
}
|
|
1188
1225
|
}
|
|
1189
1226
|
},
|
|
@@ -1199,15 +1236,18 @@ function createEvents(store) {
|
|
|
1199
1236
|
}
|
|
1200
1237
|
return intersections;
|
|
1201
1238
|
}
|
|
1202
|
-
function cancelPointer(intersections) {
|
|
1239
|
+
function cancelPointer(intersections, pointerId) {
|
|
1203
1240
|
const { internal } = store.getState();
|
|
1204
|
-
|
|
1241
|
+
const pid = pointerId ?? DEFAULT_POINTER_ID;
|
|
1242
|
+
const pointerState = internal.pointerMap.get(pid);
|
|
1243
|
+
if (!pointerState) return;
|
|
1244
|
+
for (const [hoveredId, hoveredObj] of pointerState.hovered) {
|
|
1205
1245
|
if (!intersections.length || !intersections.find(
|
|
1206
1246
|
(hit) => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId
|
|
1207
1247
|
)) {
|
|
1208
1248
|
const eventObject = hoveredObj.eventObject;
|
|
1209
1249
|
const instance = eventObject.__r3f;
|
|
1210
|
-
|
|
1250
|
+
pointerState.hovered.delete(hoveredId);
|
|
1211
1251
|
if (instance?.eventCount) {
|
|
1212
1252
|
const handlers = instance.handlers;
|
|
1213
1253
|
const data = { ...hoveredObj, intersections };
|
|
@@ -1236,41 +1276,118 @@ function createEvents(store) {
|
|
|
1236
1276
|
instance?.handlers.onDropMissed?.(event);
|
|
1237
1277
|
}
|
|
1238
1278
|
}
|
|
1279
|
+
function cleanupPointer(pointerId) {
|
|
1280
|
+
const { internal } = store.getState();
|
|
1281
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1282
|
+
if (pointerState) {
|
|
1283
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1284
|
+
const eventObject = hoveredObj.eventObject;
|
|
1285
|
+
const instance = eventObject.__r3f;
|
|
1286
|
+
if (instance?.eventCount) {
|
|
1287
|
+
const handlers = instance.handlers;
|
|
1288
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1289
|
+
handlers.onPointerOut?.(data);
|
|
1290
|
+
handlers.onPointerLeave?.(data);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
internal.pointerMap.delete(pointerId);
|
|
1294
|
+
}
|
|
1295
|
+
internal.pointerDirty.delete(pointerId);
|
|
1296
|
+
}
|
|
1297
|
+
function processDeferredPointer(event, pointerId) {
|
|
1298
|
+
const state = store.getState();
|
|
1299
|
+
const { onPointerMissed, onDragOverMissed, internal } = state;
|
|
1300
|
+
if (!state.events.enabled) return;
|
|
1301
|
+
const filter = filterPointerEvents;
|
|
1302
|
+
const hits = intersect(event, filter);
|
|
1303
|
+
cancelPointer(hits, pointerId);
|
|
1304
|
+
function onIntersect(data) {
|
|
1305
|
+
const eventObject = data.eventObject;
|
|
1306
|
+
const instance = eventObject.__r3f;
|
|
1307
|
+
if (!instance?.eventCount) return;
|
|
1308
|
+
const handlers = instance.handlers;
|
|
1309
|
+
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
1310
|
+
const id = makeId(data);
|
|
1311
|
+
const pointerState = getPointerState(internal, pointerId);
|
|
1312
|
+
const hoveredItem = pointerState.hovered.get(id);
|
|
1313
|
+
if (!hoveredItem) {
|
|
1314
|
+
pointerState.hovered.set(id, data);
|
|
1315
|
+
handlers.onPointerOver?.(data);
|
|
1316
|
+
handlers.onPointerEnter?.(data);
|
|
1317
|
+
} else if (hoveredItem.stopped) {
|
|
1318
|
+
data.stopPropagation();
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
handlers.onPointerMove?.(data);
|
|
1322
|
+
}
|
|
1323
|
+
handleIntersects(hits, event, 0, onIntersect);
|
|
1324
|
+
}
|
|
1239
1325
|
function handlePointer(name) {
|
|
1240
1326
|
switch (name) {
|
|
1241
1327
|
case "onPointerLeave":
|
|
1242
|
-
case "onPointerCancel":
|
|
1243
1328
|
case "onDragLeave":
|
|
1244
1329
|
return () => cancelPointer([]);
|
|
1330
|
+
// Global cancel of these events
|
|
1331
|
+
case "onPointerCancel":
|
|
1332
|
+
return (event) => {
|
|
1333
|
+
const pointerId = getPointerId(event);
|
|
1334
|
+
cleanupPointer(pointerId);
|
|
1335
|
+
};
|
|
1245
1336
|
case "onLostPointerCapture":
|
|
1246
1337
|
return (event) => {
|
|
1247
1338
|
const { internal } = store.getState();
|
|
1248
|
-
|
|
1339
|
+
const pointerId = getPointerId(event);
|
|
1340
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1341
|
+
if (pointerState?.captured.size) {
|
|
1249
1342
|
requestAnimationFrame(() => {
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1343
|
+
const pointerState2 = internal.pointerMap.get(pointerId);
|
|
1344
|
+
if (pointerState2?.captured.size) {
|
|
1345
|
+
pointerState2.captured.clear();
|
|
1253
1346
|
}
|
|
1347
|
+
cancelPointer([], pointerId);
|
|
1254
1348
|
});
|
|
1255
1349
|
}
|
|
1256
1350
|
};
|
|
1257
1351
|
}
|
|
1258
1352
|
return function handleEvent(event) {
|
|
1259
1353
|
const state = store.getState();
|
|
1260
|
-
const { onPointerMissed, onDragOverMissed, onDropMissed, internal } = state;
|
|
1354
|
+
const { onPointerMissed, onDragOverMissed, onDropMissed, internal, events } = state;
|
|
1355
|
+
const pointerId = getPointerId(event);
|
|
1261
1356
|
internal.lastEvent.current = event;
|
|
1262
|
-
if (!
|
|
1357
|
+
if (!events.enabled) return;
|
|
1263
1358
|
const isPointerMove = name === "onPointerMove";
|
|
1264
1359
|
const isDragOver = name === "onDragOver";
|
|
1265
1360
|
const isDrop = name === "onDrop";
|
|
1266
1361
|
const isClickEvent = name === "onClick" || name === "onContextMenu" || name === "onDoubleClick";
|
|
1362
|
+
const isPointerDown = name === "onPointerDown";
|
|
1363
|
+
const isPointerUp = name === "onPointerUp";
|
|
1364
|
+
const isWheel = name === "onWheel";
|
|
1365
|
+
const canDeferRaycasts = events.frameTimedRaycasts && state.frameloop === "always";
|
|
1366
|
+
if (isPointerMove && canDeferRaycasts) {
|
|
1367
|
+
events.compute?.(event, state);
|
|
1368
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
if (isWheel && canDeferRaycasts && !events.alwaysFireOnScroll) {
|
|
1372
|
+
events.compute?.(event, state);
|
|
1373
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
if ((isClickEvent || isPointerDown || isPointerUp) && internal.pointerDirty.has(pointerId)) {
|
|
1377
|
+
const deferredEvent = internal.pointerDirty.get(pointerId);
|
|
1378
|
+
internal.pointerDirty.delete(pointerId);
|
|
1379
|
+
processDeferredPointer(deferredEvent, pointerId);
|
|
1380
|
+
}
|
|
1267
1381
|
const filter = isPointerMove || isDragOver || isDrop ? filterPointerEvents : void 0;
|
|
1268
1382
|
const hits = intersect(event, filter);
|
|
1269
|
-
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
1270
|
-
if (
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1383
|
+
const delta = isClickEvent ? calculateDistance(event, pointerId) : 0;
|
|
1384
|
+
if (isPointerDown) {
|
|
1385
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1386
|
+
pointerState2.initialClick = [event.offsetX, event.offsetY];
|
|
1387
|
+
pointerState2.initialHits = hits.map((hit) => hit.eventObject);
|
|
1388
|
+
}
|
|
1389
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1390
|
+
const initialHits = pointerState?.initialHits ?? [];
|
|
1274
1391
|
if (isClickEvent && !hits.length) {
|
|
1275
1392
|
if (delta <= 2) {
|
|
1276
1393
|
pointerMissed(event, internal.interaction);
|
|
@@ -1285,7 +1402,9 @@ function createEvents(store) {
|
|
|
1285
1402
|
dropMissed(event, internal.interaction);
|
|
1286
1403
|
if (onDropMissed) onDropMissed(event);
|
|
1287
1404
|
}
|
|
1288
|
-
if (isPointerMove || isDragOver)
|
|
1405
|
+
if (isPointerMove || isDragOver) {
|
|
1406
|
+
cancelPointer(hits, pointerId);
|
|
1407
|
+
}
|
|
1289
1408
|
function onIntersect(data) {
|
|
1290
1409
|
const eventObject = data.eventObject;
|
|
1291
1410
|
const instance = eventObject.__r3f;
|
|
@@ -1294,9 +1413,10 @@ function createEvents(store) {
|
|
|
1294
1413
|
if (isPointerMove) {
|
|
1295
1414
|
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
1296
1415
|
const id = makeId(data);
|
|
1297
|
-
const
|
|
1416
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1417
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
1298
1418
|
if (!hoveredItem) {
|
|
1299
|
-
|
|
1419
|
+
pointerState2.hovered.set(id, data);
|
|
1300
1420
|
handlers.onPointerOver?.(data);
|
|
1301
1421
|
handlers.onPointerEnter?.(data);
|
|
1302
1422
|
} else if (hoveredItem.stopped) {
|
|
@@ -1306,9 +1426,10 @@ function createEvents(store) {
|
|
|
1306
1426
|
handlers.onPointerMove?.(data);
|
|
1307
1427
|
} else if (isDragOver) {
|
|
1308
1428
|
const id = makeId(data);
|
|
1309
|
-
const
|
|
1429
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1430
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
1310
1431
|
if (!hoveredItem) {
|
|
1311
|
-
|
|
1432
|
+
pointerState2.hovered.set(id, data);
|
|
1312
1433
|
handlers.onDragOverEnter?.(data);
|
|
1313
1434
|
} else if (hoveredItem.stopped) {
|
|
1314
1435
|
data.stopPropagation();
|
|
@@ -1319,18 +1440,18 @@ function createEvents(store) {
|
|
|
1319
1440
|
} else {
|
|
1320
1441
|
const handler = handlers[name];
|
|
1321
1442
|
if (handler) {
|
|
1322
|
-
if (!isClickEvent ||
|
|
1443
|
+
if (!isClickEvent || initialHits.includes(eventObject)) {
|
|
1323
1444
|
pointerMissed(
|
|
1324
1445
|
event,
|
|
1325
|
-
internal.interaction.filter((object) => !
|
|
1446
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
1326
1447
|
);
|
|
1327
1448
|
handler(data);
|
|
1328
1449
|
}
|
|
1329
1450
|
} else {
|
|
1330
|
-
if (isClickEvent &&
|
|
1451
|
+
if (isClickEvent && initialHits.includes(eventObject)) {
|
|
1331
1452
|
pointerMissed(
|
|
1332
1453
|
event,
|
|
1333
|
-
internal.interaction.filter((object) => !
|
|
1454
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
1334
1455
|
);
|
|
1335
1456
|
}
|
|
1336
1457
|
}
|
|
@@ -1339,7 +1460,15 @@ function createEvents(store) {
|
|
|
1339
1460
|
handleIntersects(hits, event, delta, onIntersect);
|
|
1340
1461
|
};
|
|
1341
1462
|
}
|
|
1342
|
-
|
|
1463
|
+
function flushDeferredPointers() {
|
|
1464
|
+
const { internal, events } = store.getState();
|
|
1465
|
+
if (!events.frameTimedRaycasts) return;
|
|
1466
|
+
for (const [pointerId, event] of internal.pointerDirty) {
|
|
1467
|
+
processDeferredPointer(event, pointerId);
|
|
1468
|
+
}
|
|
1469
|
+
internal.pointerDirty.clear();
|
|
1470
|
+
}
|
|
1471
|
+
return { handlePointer, flushDeferredPointers, processDeferredPointer };
|
|
1343
1472
|
}
|
|
1344
1473
|
const DOM_EVENTS = {
|
|
1345
1474
|
onClick: ["click", false],
|
|
@@ -1358,10 +1487,15 @@ const DOM_EVENTS = {
|
|
|
1358
1487
|
onLostPointerCapture: ["lostpointercapture", true]
|
|
1359
1488
|
};
|
|
1360
1489
|
function createPointerEvents(store) {
|
|
1361
|
-
const { handlePointer } = createEvents(store);
|
|
1490
|
+
const { handlePointer, flushDeferredPointers, processDeferredPointer } = createEvents(store);
|
|
1491
|
+
let nextXRPointerId = XR_POINTER_ID_START;
|
|
1492
|
+
const xrPointers = /* @__PURE__ */ new Map();
|
|
1362
1493
|
return {
|
|
1363
1494
|
priority: 1,
|
|
1364
1495
|
enabled: true,
|
|
1496
|
+
frameTimedRaycasts: true,
|
|
1497
|
+
alwaysFireOnScroll: true,
|
|
1498
|
+
updateOnFrame: false,
|
|
1365
1499
|
compute(event, state) {
|
|
1366
1500
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
1367
1501
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
@@ -1371,9 +1505,30 @@ function createPointerEvents(store) {
|
|
|
1371
1505
|
(acc, key) => ({ ...acc, [key]: handlePointer(key) }),
|
|
1372
1506
|
{}
|
|
1373
1507
|
),
|
|
1374
|
-
update: () => {
|
|
1508
|
+
update: (pointerId) => {
|
|
1375
1509
|
const { events, internal } = store.getState();
|
|
1376
|
-
if (
|
|
1510
|
+
if (!events.handlers) return;
|
|
1511
|
+
if (pointerId !== void 0) {
|
|
1512
|
+
const event = internal.pointerDirty.get(pointerId);
|
|
1513
|
+
if (event) {
|
|
1514
|
+
internal.pointerDirty.delete(pointerId);
|
|
1515
|
+
processDeferredPointer(event, pointerId);
|
|
1516
|
+
} else if (internal.lastEvent?.current) {
|
|
1517
|
+
processDeferredPointer(internal.lastEvent.current, pointerId);
|
|
1518
|
+
}
|
|
1519
|
+
} else {
|
|
1520
|
+
flushDeferredPointers();
|
|
1521
|
+
if (internal.lastEvent?.current) {
|
|
1522
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
},
|
|
1526
|
+
flush: () => {
|
|
1527
|
+
const { events, internal } = store.getState();
|
|
1528
|
+
flushDeferredPointers();
|
|
1529
|
+
if (events.updateOnFrame && internal.lastEvent?.current && events.handlers) {
|
|
1530
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1531
|
+
}
|
|
1377
1532
|
},
|
|
1378
1533
|
connect: (target) => {
|
|
1379
1534
|
const { set, events } = store.getState();
|
|
@@ -1399,6 +1554,32 @@ function createPointerEvents(store) {
|
|
|
1399
1554
|
}
|
|
1400
1555
|
set((state) => ({ events: { ...state.events, connected: void 0 } }));
|
|
1401
1556
|
}
|
|
1557
|
+
},
|
|
1558
|
+
registerPointer: (config) => {
|
|
1559
|
+
const pointerId = nextXRPointerId++;
|
|
1560
|
+
xrPointers.set(pointerId, config);
|
|
1561
|
+
const { internal } = store.getState();
|
|
1562
|
+
getPointerState(internal, pointerId);
|
|
1563
|
+
return pointerId;
|
|
1564
|
+
},
|
|
1565
|
+
unregisterPointer: (pointerId) => {
|
|
1566
|
+
xrPointers.delete(pointerId);
|
|
1567
|
+
const { internal } = store.getState();
|
|
1568
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1569
|
+
if (pointerState) {
|
|
1570
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1571
|
+
const eventObject = hoveredObj.eventObject;
|
|
1572
|
+
const instance = eventObject.__r3f;
|
|
1573
|
+
if (instance?.eventCount) {
|
|
1574
|
+
const handlers = instance.handlers;
|
|
1575
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1576
|
+
handlers.onPointerOut?.(data);
|
|
1577
|
+
handlers.onPointerLeave?.(data);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
internal.pointerMap.delete(pointerId);
|
|
1581
|
+
}
|
|
1582
|
+
internal.pointerDirty.delete(pointerId);
|
|
1402
1583
|
}
|
|
1403
1584
|
};
|
|
1404
1585
|
}
|
|
@@ -2529,7 +2710,14 @@ const createStore = (invalidate, advance) => {
|
|
|
2529
2710
|
frustum: new three.Frustum(),
|
|
2530
2711
|
autoUpdateFrustum: true,
|
|
2531
2712
|
raycaster: null,
|
|
2532
|
-
events: {
|
|
2713
|
+
events: {
|
|
2714
|
+
priority: 1,
|
|
2715
|
+
enabled: true,
|
|
2716
|
+
connected: false,
|
|
2717
|
+
frameTimedRaycasts: true,
|
|
2718
|
+
alwaysFireOnScroll: true,
|
|
2719
|
+
updateOnFrame: false
|
|
2720
|
+
},
|
|
2533
2721
|
scene: null,
|
|
2534
2722
|
rootScene: null,
|
|
2535
2723
|
xr: null,
|
|
@@ -2620,11 +2808,13 @@ const createStore = (invalidate, advance) => {
|
|
|
2620
2808
|
},
|
|
2621
2809
|
setError: (error) => set(() => ({ error })),
|
|
2622
2810
|
error: null,
|
|
2623
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures,
|
|
2811
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
2624
2812
|
uniforms: {},
|
|
2625
2813
|
nodes: {},
|
|
2814
|
+
buffers: {},
|
|
2815
|
+
gpuStorage: {},
|
|
2626
2816
|
textures: /* @__PURE__ */ new Map(),
|
|
2627
|
-
|
|
2817
|
+
renderPipeline: null,
|
|
2628
2818
|
passes: {},
|
|
2629
2819
|
_hmrVersion: 0,
|
|
2630
2820
|
_sizeImperative: false,
|
|
@@ -2633,12 +2823,16 @@ const createStore = (invalidate, advance) => {
|
|
|
2633
2823
|
internal: {
|
|
2634
2824
|
// Events
|
|
2635
2825
|
interaction: [],
|
|
2636
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
2637
2826
|
subscribers: [],
|
|
2827
|
+
// Per-pointer state (new unified structure)
|
|
2828
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
2829
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
2830
|
+
lastEvent: React__namespace.createRef(),
|
|
2831
|
+
// Deprecated but kept for backwards compatibility
|
|
2832
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
2638
2833
|
initialClick: [0, 0],
|
|
2639
2834
|
initialHits: [],
|
|
2640
2835
|
capturedMap: /* @__PURE__ */ new Map(),
|
|
2641
|
-
lastEvent: React__namespace.createRef(),
|
|
2642
2836
|
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
2643
2837
|
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
2644
2838
|
// Occlusion system (WebGPU only)
|
|
@@ -15248,6 +15442,18 @@ function createRoot(canvas) {
|
|
|
15248
15442
|
system: true
|
|
15249
15443
|
}
|
|
15250
15444
|
);
|
|
15445
|
+
const unregisterEventsFlush = scheduler.register(
|
|
15446
|
+
() => {
|
|
15447
|
+
const state2 = store.getState();
|
|
15448
|
+
state2.events.flush?.();
|
|
15449
|
+
},
|
|
15450
|
+
{
|
|
15451
|
+
id: `${newRootId}_events`,
|
|
15452
|
+
rootId: newRootId,
|
|
15453
|
+
phase: "input",
|
|
15454
|
+
system: true
|
|
15455
|
+
}
|
|
15456
|
+
);
|
|
15251
15457
|
const unregisterFrustum = scheduler.register(
|
|
15252
15458
|
() => {
|
|
15253
15459
|
const state2 = store.getState();
|
|
@@ -15282,7 +15488,7 @@ function createRoot(canvas) {
|
|
|
15282
15488
|
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
15283
15489
|
if (userHandlesRender || state2.internal.priority) return;
|
|
15284
15490
|
try {
|
|
15285
|
-
if (state2.
|
|
15491
|
+
if (state2.renderPipeline?.render) state2.renderPipeline.render();
|
|
15286
15492
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
15287
15493
|
} catch (error) {
|
|
15288
15494
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -15307,6 +15513,7 @@ function createRoot(canvas) {
|
|
|
15307
15513
|
unregisterRoot: () => {
|
|
15308
15514
|
unregisterRoot();
|
|
15309
15515
|
unregisterCanvasTarget();
|
|
15516
|
+
unregisterEventsFlush();
|
|
15310
15517
|
unregisterFrustum();
|
|
15311
15518
|
unregisterVisibility();
|
|
15312
15519
|
unregisterRender();
|
|
@@ -15472,9 +15679,13 @@ function PortalInner({ state = {}, children, container }) {
|
|
|
15472
15679
|
const store = traditional.createWithEqualityFn((set, get) => ({ ...rest, set, get }));
|
|
15473
15680
|
const onMutate = (prev) => store.setState((state2) => inject.current(prev, state2));
|
|
15474
15681
|
onMutate(previousRoot.getState());
|
|
15475
|
-
previousRoot.subscribe(onMutate);
|
|
15476
15682
|
return store;
|
|
15477
15683
|
}, [previousRoot, container]);
|
|
15684
|
+
useIsomorphicLayoutEffect(() => {
|
|
15685
|
+
const onMutate = (prev) => usePortalStore.setState((state2) => inject.current(prev, state2));
|
|
15686
|
+
const unsubscribe = previousRoot.subscribe(onMutate);
|
|
15687
|
+
return unsubscribe;
|
|
15688
|
+
}, [previousRoot, usePortalStore]);
|
|
15478
15689
|
return (
|
|
15479
15690
|
// @ts-ignore, reconciler types are not maintained
|
|
15480
15691
|
/* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reconciler.createPortal(
|
|
@@ -15695,6 +15906,7 @@ function CanvasImpl({
|
|
|
15695
15906
|
queueMicrotask(() => {
|
|
15696
15907
|
const rootEntry = _roots.get(canvas);
|
|
15697
15908
|
if (rootEntry?.store) {
|
|
15909
|
+
console.log("[R3F] HMR detected \u2014 rebuilding nodes/uniforms");
|
|
15698
15910
|
rootEntry.store.setState((state) => ({
|
|
15699
15911
|
nodes: {},
|
|
15700
15912
|
uniforms: {},
|
|
@@ -15706,8 +15918,7 @@ function CanvasImpl({
|
|
|
15706
15918
|
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('legacy.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
15707
15919
|
const hot = undefined;
|
|
15708
15920
|
hot.on("vite:afterUpdate", handleHMR);
|
|
15709
|
-
return () => hot.
|
|
15710
|
-
});
|
|
15921
|
+
return () => hot.off?.("vite:afterUpdate", handleHMR);
|
|
15711
15922
|
}
|
|
15712
15923
|
if (typeof module !== "undefined" && module.hot) {
|
|
15713
15924
|
const hot = module.hot;
|