@@ -58,8 +58,10 @@ export type EventHandlers = {
58
58
onContextMenu ?: ( event : ThreeEvent < MouseEvent > ) => void
59
59
onDoubleClick ?: ( event : ThreeEvent < MouseEvent > ) => void
60
60
onDragOverEnter ?: ( event : ThreeEvent < DragEvent > ) => void
61
- onDragOverLeave ?: ( event : DragEvent ) => void
62
- onDrop ?: ( event : DragEvent ) => void
61
+ onDragOverLeave ?: ( event : ThreeEvent < DragEvent > ) => void
62
+ onDragOverMissed ?: ( event : DragEvent ) => void
63
+ onDrop ?: ( event : ThreeEvent < DragEvent > ) => void
64
+ onDropMissed ?: ( event : DragEvent ) => void
63
65
onPointerUp ?: ( event : ThreeEvent < PointerEvent > ) => void
64
66
onPointerDown ?: ( event : ThreeEvent < PointerEvent > ) => void
65
67
onPointerOver ?: ( event : ThreeEvent < PointerEvent > ) => void
@@ -414,14 +416,15 @@ export function createEvents(store: UseBoundStore<RootState>) {
414
416
415
417
// Any other pointer goes here ...
416
418
return ( event : DomEvent ) => {
417
- const { onPointerMissed, internal } = store . getState ( )
419
+ const { onPointerMissed, onDragOverMissed , onDropMissed , internal } = store . getState ( )
418
420
419
421
//prepareRay(event)
420
422
internal . lastEvent . current = event
421
423
422
424
// Get fresh intersects
423
425
const isPointerMove = name === 'onPointerMove'
424
426
const isDragOver = name === 'onDragOverEnter' || name === 'onDragOverLeave'
427
+ const isDrop = name === 'onDrop'
425
428
const isClickEvent = name === 'onClick' || name === 'onContextMenu' || name === 'onDoubleClick'
426
429
const filter = isPointerMove ? filterPointerEvents : undefined
427
430
//const hits = patchIntersects(intersect(filter), event)
@@ -442,6 +445,15 @@ export function createEvents(store: UseBoundStore<RootState>) {
442
445
if ( onPointerMissed ) onPointerMissed ( event )
443
446
}
444
447
}
448
+ if ( isDragOver && ! hits . length ) {
449
+ dragOverMissed ( event as DragEvent , internal . interaction )
450
+ if ( onDragOverMissed ) onDragOverMissed ( event as DragEvent )
451
+ }
452
+ if ( isDrop && ! hits . length ) {
453
+ dropMissed ( event as DragEvent , internal . interaction )
454
+ if ( onDropMissed ) onDropMissed ( event as DragEvent )
455
+ }
456
+
445
457
// Take care of unhover
446
458
if ( isPointerMove || isDragOver ) cancelPointer ( hits )
447
459
@@ -481,6 +493,11 @@ export function createEvents(store: UseBoundStore<RootState>) {
481
493
} else if ( hoveredItem . stopped ) {
482
494
// If the object was previously hovered and stopped, we shouldn't allow other items to proceed
483
495
data . stopPropagation ( )
496
+ } else if ( internal . initialHits . includes ( eventObject ) ) {
497
+ dragOverMissed (
498
+ event as DragEvent ,
499
+ internal . interaction . filter ( ( object ) => ! internal . initialHits . includes ( object ) ) ,
500
+ )
484
501
}
485
502
} else {
486
503
// All other events ...
@@ -517,5 +534,15 @@ export function createEvents(store: UseBoundStore<RootState>) {
517
534
)
518
535
}
519
536
537
+ function dragOverMissed ( event : DragEvent , objects : THREE . Object3D [ ] ) {
538
+ objects . forEach ( ( object : THREE . Object3D ) =>
539
+ ( object as unknown as Instance ) . __r3f ?. handlers . onDragOverMissed ?.( event ) ,
540
+ )
541
+ }
542
+
543
+ function dropMissed ( event : DragEvent , objects : THREE . Object3D [ ] ) {
544
+ objects . forEach ( ( object : THREE . Object3D ) => ( object as unknown as Instance ) . __r3f ?. handlers . onDropMissed ?.( event ) )
545
+ }
546
+
520
547
return { handlePointer }
521
548
}
0 commit comments