@pmndrs/pointer-events
Advanced tools
Comparing version 6.2.19 to 6.3.0
@@ -1,2 +0,2 @@ | ||
import { Object3D, Sphere, Intersection as ThreeIntersection } from 'three'; | ||
import { Object3D, Sphere } from 'three'; | ||
import { Intersection } from '../index.js'; | ||
@@ -6,11 +6,8 @@ import { PointerCapture } from '../pointer.js'; | ||
export declare function getVoidObject(scene: Object3D): Object3D; | ||
export declare abstract class Intersector { | ||
protected intersection: ThreeIntersection | undefined; | ||
protected pointerEventsOrder: number | undefined; | ||
export interface Intersector { | ||
intersectPointerCapture(pointerCapture: PointerCapture, nativeEvent: unknown): Intersection; | ||
isReady(): boolean; | ||
startIntersection(nativeEvent: unknown): void; | ||
abstract intersectPointerCapture(pointerCapture: PointerCapture, nativeEvent: unknown): Intersection; | ||
abstract isReady(): boolean; | ||
protected abstract prepareIntersection(nativeEvent: unknown): void; | ||
abstract executeIntersection(scene: Object3D, objectPointerEventsOrder: number): void; | ||
abstract finalizeIntersection(scene: Object3D): Intersection; | ||
executeIntersection(scene: Object3D, objectPointerEventsOrder: number): void; | ||
finalizeIntersection(scene: Object3D): Intersection; | ||
} |
@@ -18,11 +18,1 @@ import { Mesh, Sphere, SphereGeometry } from 'three'; | ||
} | ||
export class Intersector { | ||
//state of the current intersection | ||
intersection; | ||
pointerEventsOrder; | ||
startIntersection(nativeEvent) { | ||
this.intersection = undefined; | ||
this.pointerEventsOrder = undefined; | ||
this.prepareIntersection(nativeEvent); | ||
} | ||
} |
@@ -5,3 +5,3 @@ import { Vector3, Object3D } from 'three'; | ||
import { Intersection, IntersectionOptions } from '../index.js'; | ||
export declare class LinesIntersector extends Intersector { | ||
export declare class LinesIntersector implements Intersector { | ||
private readonly space; | ||
@@ -11,5 +11,6 @@ private readonly options; | ||
private fromMatrixWorld; | ||
private intersectionLineIndex; | ||
private intersectionDistanceOnLine; | ||
private ready?; | ||
private intersects; | ||
private readonly pointerEventsOrders; | ||
private readonly raycasterIndices; | ||
constructor(space: { | ||
@@ -24,5 +25,5 @@ current?: Object3D | null; | ||
intersectPointerCapture({ intersection, object }: PointerCapture): Intersection; | ||
protected prepareIntersection(): void; | ||
startIntersection(): void; | ||
executeIntersection(object: Object3D, objectPointerEventsOrder: number | undefined): void; | ||
finalizeIntersection(scene: Object3D): Intersection; | ||
} |
import { Line3, Matrix4, Plane, Quaternion, Ray, Raycaster, Vector3, } from 'three'; | ||
import { computeIntersectionWorldPlane, getDominantIntersectionIndex, voidObjectIntersectionFromRay } from './utils.js'; | ||
import { Intersector } from './intersector.js'; | ||
import { computeIntersectionWorldPlane, getDominantIntersectionIndex, pushTimes, voidObjectIntersectionFromRay, } from './utils.js'; | ||
import { updateAndCheckWorldTransformation } from '../utils.js'; | ||
const invertedMatrixHelper = new Matrix4(); | ||
const intersectsHelper = []; | ||
const lineHelper = new Line3(); | ||
@@ -11,3 +9,3 @@ const planeHelper = new Plane(); | ||
const defaultLinePoints = [new Vector3(0, 0, 0), new Vector3(0, 0, 1)]; | ||
export class LinesIntersector extends Intersector { | ||
export class LinesIntersector { | ||
space; | ||
@@ -17,8 +15,7 @@ options; | ||
fromMatrixWorld = new Matrix4(); | ||
//state | ||
intersectionLineIndex = 0; | ||
intersectionDistanceOnLine = 0; | ||
ready; | ||
intersects = []; | ||
pointerEventsOrders = []; | ||
raycasterIndices = []; | ||
constructor(space, options) { | ||
super(); | ||
this.space = space; | ||
@@ -63,3 +60,3 @@ this.options = options; | ||
} | ||
prepareIntersection() { | ||
startIntersection() { | ||
if (!this.prepareTransformation()) { | ||
@@ -90,21 +87,11 @@ return; | ||
} | ||
let lineLengthSum = 0; | ||
const startOuter = this.intersects.length; | ||
const length = this.raycasters.length; | ||
//TODO: optimize - we only need to intersect with raycasters before or equal to the raycaster that did the current intersection | ||
for (let i = 0; i < length; i++) { | ||
const raycaster = this.raycasters[i]; | ||
object.raycast(raycaster, intersectsHelper); | ||
for (const intersection of intersectsHelper) { | ||
intersection.distance += lineLengthSum; | ||
} | ||
const index = getDominantIntersectionIndex(this.intersection, this.pointerEventsOrder, intersectsHelper, objectPointerEventsOrder, this.options); | ||
if (index != null) { | ||
this.intersection = intersectsHelper[index]; | ||
this.intersectionLineIndex = i; | ||
this.intersectionDistanceOnLine = this.intersection.distance - raycaster.far; | ||
this.pointerEventsOrder = objectPointerEventsOrder; | ||
} | ||
intersectsHelper.length = 0; | ||
lineLengthSum += raycaster.far; | ||
const startInner = this.intersects.length; | ||
object.raycast(raycaster, this.intersects); | ||
pushTimes(this.raycasterIndices, i, this.intersects.length - startInner); | ||
} | ||
pushTimes(this.pointerEventsOrders, objectPointerEventsOrder, this.intersects.length - startOuter); | ||
} | ||
@@ -114,3 +101,9 @@ finalizeIntersection(scene) { | ||
const pointerQuaternion = new Quaternion().setFromRotationMatrix(this.fromMatrixWorld); | ||
if (this.intersection == null) { | ||
const index = getDominantIntersectionIndex(this.intersects, this.pointerEventsOrders, this.options); | ||
const intersection = index == null ? undefined : this.intersects[index]; | ||
const raycasterIndex = index == null ? undefined : this.raycasterIndices[index]; | ||
this.intersects.length = 0; | ||
this.raycasterIndices.length = 0; | ||
this.pointerEventsOrders.length = 0; | ||
if (intersection == null || raycasterIndex == null) { | ||
const lastRaycasterIndex = this.raycasters.length - 1; | ||
@@ -125,17 +118,22 @@ const prevDistance = this.raycasters.reduce((prev, caster, i) => (i === lastRaycasterIndex ? prev : prev + caster.far), 0); | ||
} | ||
let distance = intersection.distance; | ||
for (let i = 0; i < raycasterIndex; i++) { | ||
distance += this.raycasters[i].far; | ||
} | ||
//TODO: consider maxLength | ||
return Object.assign(this.intersection, { | ||
return Object.assign(intersection, { | ||
details: { | ||
lineIndex: this.intersectionLineIndex, | ||
distanceOnLine: this.intersectionDistanceOnLine, | ||
lineIndex: raycasterIndex, | ||
distanceOnLine: intersection.distance, | ||
type: 'lines', | ||
}, | ||
distance, | ||
pointerPosition, | ||
pointerQuaternion, | ||
pointOnFace: this.intersection.point, | ||
localPoint: this.intersection.point | ||
pointOnFace: intersection.point, | ||
localPoint: intersection.point | ||
.clone() | ||
.applyMatrix4(invertedMatrixHelper.copy(this.intersection.object.matrixWorld).invert()), | ||
.applyMatrix4(invertedMatrixHelper.copy(intersection.object.matrixWorld).invert()), | ||
}); | ||
} | ||
} |
@@ -5,3 +5,3 @@ import { Vector3, Object3D, Camera, Vector2 } from 'three'; | ||
import { Intersector } from './intersector.js'; | ||
export declare class RayIntersector extends Intersector { | ||
export declare class RayIntersector implements Intersector { | ||
private readonly space; | ||
@@ -13,2 +13,4 @@ private readonly options; | ||
private ready?; | ||
private readonly intersects; | ||
private readonly pointerEventsOrders; | ||
constructor(space: { | ||
@@ -23,7 +25,7 @@ current?: Object3D | null; | ||
intersectPointerCapture({ intersection, object }: PointerCapture): Intersection; | ||
protected prepareIntersection(): void; | ||
startIntersection(): void; | ||
executeIntersection(object: Object3D, objectPointerEventsOrder: number | undefined): void; | ||
finalizeIntersection(scene: Object3D): Intersection; | ||
} | ||
export declare class CameraRayIntersector extends Intersector { | ||
export declare class CameraRayIntersector implements Intersector { | ||
private readonly prepareTransformation; | ||
@@ -36,8 +38,10 @@ private readonly options; | ||
private viewPlane; | ||
private readonly intersects; | ||
private readonly pointerEventsOrders; | ||
constructor(prepareTransformation: (nativeEvent: unknown, coords: Vector2) => Camera | undefined, options: IntersectionOptions); | ||
isReady(): boolean; | ||
intersectPointerCapture({ intersection, object }: PointerCapture, nativeEvent: unknown): Intersection; | ||
protected prepareIntersection(nativeEvent: unknown): boolean; | ||
startIntersection(nativeEvent: unknown): boolean; | ||
executeIntersection(object: Object3D, objectPointerEventsOrder: number | undefined): void; | ||
finalizeIntersection(scene: Object3D): Intersection; | ||
} |
import { Matrix4, Plane, Quaternion, Raycaster, Vector3, Vector2, } from 'three'; | ||
import { computeIntersectionWorldPlane, getDominantIntersectionIndex, voidObjectIntersectionFromRay } from './utils.js'; | ||
import { Intersector } from './intersector.js'; | ||
import { computeIntersectionWorldPlane, getDominantIntersectionIndex, pushTimes, voidObjectIntersectionFromRay, } from './utils.js'; | ||
import { updateAndCheckWorldTransformation } from '../utils.js'; | ||
const invertedMatrixHelper = new Matrix4(); | ||
const intersectsHelper = []; | ||
const scaleHelper = new Vector3(); | ||
@@ -11,3 +9,3 @@ const NegZAxis = new Vector3(0, 0, -1); | ||
const planeHelper = new Plane(); | ||
export class RayIntersector extends Intersector { | ||
export class RayIntersector { | ||
space; | ||
@@ -19,4 +17,5 @@ options; | ||
ready; | ||
intersects = []; | ||
pointerEventsOrders = []; | ||
constructor(space, options) { | ||
super(); | ||
this.space = space; | ||
@@ -61,3 +60,3 @@ this.options = options; | ||
} | ||
prepareIntersection() { | ||
startIntersection() { | ||
this.prepareTransformation(); | ||
@@ -69,19 +68,5 @@ } | ||
} | ||
object.raycast(this.raycaster, intersectsHelper); | ||
//filtering out all intersections that are to near | ||
if (this.options.minDistance != null) { | ||
const length = intersectsHelper.length; | ||
const localMinDistance = this.options.minDistance / this.worldScale; | ||
for (let i = length - 1; i >= 0; i--) { | ||
if (intersectsHelper[i].distance < localMinDistance) { | ||
intersectsHelper.splice(i, 1); | ||
} | ||
} | ||
} | ||
const index = getDominantIntersectionIndex(this.intersection, this.pointerEventsOrder, intersectsHelper, objectPointerEventsOrder, this.options); | ||
if (index != null) { | ||
this.intersection = intersectsHelper[index]; | ||
this.pointerEventsOrder = objectPointerEventsOrder; | ||
} | ||
intersectsHelper.length = 0; | ||
const start = this.intersects.length; | ||
object.raycast(this.raycaster, this.intersects); | ||
pushTimes(this.pointerEventsOrders, objectPointerEventsOrder, this.intersects.length - start); | ||
} | ||
@@ -91,6 +76,15 @@ finalizeIntersection(scene) { | ||
const pointerQuaternion = this.raycasterQuaternion.clone(); | ||
if (this.intersection == null) { | ||
let filter; | ||
if (this.options.minDistance != null) { | ||
const localMinDistance = this.options.minDistance / this.worldScale; | ||
filter = (intersection) => intersection.distance >= localMinDistance; | ||
} | ||
const index = getDominantIntersectionIndex(this.intersects, this.pointerEventsOrders, this.options, filter); | ||
const intersection = index == null ? undefined : this.intersects[index]; | ||
this.intersects.length = 0; | ||
this.pointerEventsOrders.length = 0; | ||
if (intersection == null) { | ||
return voidObjectIntersectionFromRay(scene, this.raycaster.ray, () => ({ type: 'ray' }), pointerPosition, pointerQuaternion); | ||
} | ||
return Object.assign(this.intersection, { | ||
return Object.assign(intersection, { | ||
details: { | ||
@@ -101,10 +95,10 @@ type: 'ray', | ||
pointerQuaternion, | ||
pointOnFace: this.intersection.point, | ||
localPoint: this.intersection.point | ||
pointOnFace: intersection.point, | ||
localPoint: intersection.point | ||
.clone() | ||
.applyMatrix4(invertedMatrixHelper.copy(this.intersection.object.matrixWorld).invert()), | ||
.applyMatrix4(invertedMatrixHelper.copy(intersection.object.matrixWorld).invert()), | ||
}); | ||
} | ||
} | ||
export class CameraRayIntersector extends Intersector { | ||
export class CameraRayIntersector { | ||
prepareTransformation; | ||
@@ -117,4 +111,5 @@ options; | ||
viewPlane = new Plane(); | ||
intersects = []; | ||
pointerEventsOrders = []; | ||
constructor(prepareTransformation, options) { | ||
super(); | ||
this.prepareTransformation = prepareTransformation; | ||
@@ -131,3 +126,3 @@ this.options = options; | ||
} | ||
if (!this.prepareIntersection(nativeEvent)) { | ||
if (!this.startIntersection(nativeEvent)) { | ||
return intersection; | ||
@@ -151,3 +146,3 @@ } | ||
} | ||
prepareIntersection(nativeEvent) { | ||
startIntersection(nativeEvent) { | ||
const from = this.prepareTransformation(nativeEvent, this.coords); | ||
@@ -164,9 +159,5 @@ if (from == null) { | ||
executeIntersection(object, objectPointerEventsOrder) { | ||
object.raycast(this.raycaster, intersectsHelper); | ||
const index = getDominantIntersectionIndex(this.intersection, this.pointerEventsOrder, intersectsHelper, objectPointerEventsOrder, this.options); | ||
if (index != null) { | ||
this.intersection = intersectsHelper[index]; | ||
this.pointerEventsOrder = objectPointerEventsOrder; | ||
} | ||
intersectsHelper.length = 0; | ||
const start = this.intersects.length; | ||
object.raycast(this.raycaster, this.intersects); | ||
pushTimes(this.pointerEventsOrders, objectPointerEventsOrder, this.intersects.length - start); | ||
} | ||
@@ -176,17 +167,21 @@ finalizeIntersection(scene) { | ||
const pointerQuaternion = this.fromQuaternion.clone(); | ||
if (this.intersection == null) { | ||
const index = getDominantIntersectionIndex(this.intersects, this.pointerEventsOrders, this.options); | ||
const intersection = index == null ? undefined : this.intersects[index]; | ||
this.intersects.length = 0; | ||
this.pointerEventsOrders.length = 0; | ||
if (intersection == null) { | ||
return voidObjectIntersectionFromRay(scene, this.raycaster.ray, (distance) => ({ type: 'camera-ray', distanceViewPlane: distance }), pointerPosition, pointerQuaternion); | ||
} | ||
invertedMatrixHelper.copy(this.intersection.object.matrixWorld).invert(); | ||
return Object.assign(this.intersection, { | ||
invertedMatrixHelper.copy(intersection.object.matrixWorld).invert(); | ||
return Object.assign(intersection, { | ||
details: { | ||
type: 'camera-ray', | ||
distanceViewPlane: this.viewPlane.distanceToPoint(this.intersection.point), | ||
distanceViewPlane: this.viewPlane.distanceToPoint(intersection.point), | ||
}, | ||
pointOnFace: this.intersection.point, | ||
pointOnFace: intersection.point, | ||
pointerPosition, | ||
pointerQuaternion, | ||
localPoint: this.intersection.point.clone().applyMatrix4(invertedMatrixHelper), | ||
localPoint: intersection.point.clone().applyMatrix4(invertedMatrixHelper), | ||
}); | ||
} | ||
} |
@@ -5,3 +5,3 @@ import { Object3D } from 'three'; | ||
import { Intersection, IntersectionOptions } from '../index.js'; | ||
export declare class SphereIntersector extends Intersector { | ||
export declare class SphereIntersector implements Intersector { | ||
private readonly space; | ||
@@ -14,2 +14,4 @@ private readonly getSphereRadius; | ||
private ready?; | ||
private readonly intersects; | ||
private readonly pointerEventsOrders; | ||
constructor(space: { | ||
@@ -21,5 +23,5 @@ current?: Object3D | null; | ||
intersectPointerCapture({ intersection, object }: PointerCapture): Intersection; | ||
protected prepareIntersection(): void; | ||
startIntersection(): void; | ||
executeIntersection(object: Object3D, objectPointerEventsOrder: number | undefined): void; | ||
finalizeIntersection(scene: Object3D): Intersection; | ||
} |
import { InstancedMesh, Matrix4, Mesh, Vector3, Sphere, Quaternion, Plane, } from 'three'; | ||
import { computeIntersectionWorldPlane, getDominantIntersectionIndex } from './utils.js'; | ||
import { Intersector } from './intersector.js'; | ||
import { computeIntersectionWorldPlane, getDominantIntersectionIndex, pushTimes } from './utils.js'; | ||
import { getVoidObject } from '../index.js'; | ||
import { updateAndCheckWorldTransformation } from '../utils.js'; | ||
const intersectsHelper = []; | ||
const scaleHelper = new Vector3(); | ||
export class SphereIntersector extends Intersector { | ||
export class SphereIntersector { | ||
space; | ||
@@ -16,4 +14,5 @@ getSphereRadius; | ||
ready; | ||
intersects = []; | ||
pointerEventsOrders = []; | ||
constructor(space, getSphereRadius, options) { | ||
super(); | ||
this.space = space; | ||
@@ -67,3 +66,3 @@ this.getSphereRadius = getSphereRadius; | ||
} | ||
prepareIntersection() { | ||
startIntersection() { | ||
if (!this.prepareTransformation()) { | ||
@@ -79,10 +78,5 @@ return; | ||
} | ||
intersectsHelper.length = 0; | ||
intersectSphereWithObject(this.collisionSphere, object, intersectsHelper); | ||
const index = getDominantIntersectionIndex(this.intersection, this.pointerEventsOrder, intersectsHelper, objectPointerEventsOrder, this.options); | ||
if (index != null) { | ||
this.intersection = intersectsHelper[index]; | ||
this.pointerEventsOrder = objectPointerEventsOrder; | ||
} | ||
intersectsHelper.length = 0; | ||
const start = this.intersects.length; | ||
intersectSphereWithObject(this.collisionSphere, object, this.intersects); | ||
pushTimes(this.pointerEventsOrders, objectPointerEventsOrder, this.intersects.length - start); | ||
} | ||
@@ -92,3 +86,7 @@ finalizeIntersection(scene) { | ||
const pointerQuaternion = this.fromQuaternion.clone(); | ||
if (this.intersection == null) { | ||
const index = getDominantIntersectionIndex(this.intersects, this.pointerEventsOrders, this.options); | ||
const intersection = index == null ? undefined : this.intersects[index]; | ||
this.intersects.length = 0; | ||
this.pointerEventsOrders.length = 0; | ||
if (intersection == null) { | ||
return { | ||
@@ -107,12 +105,12 @@ details: { | ||
} | ||
return Object.assign(this.intersection, { | ||
return Object.assign(intersection, { | ||
details: { | ||
type: 'sphere', | ||
}, | ||
pointOnFace: this.intersection.point, | ||
pointOnFace: intersection.point, | ||
pointerPosition: this.fromPosition.clone(), | ||
pointerQuaternion: this.fromQuaternion.clone(), | ||
localPoint: this.intersection.point | ||
localPoint: intersection.point | ||
.clone() | ||
.applyMatrix4(invertedMatrixHelper.copy(this.intersection.object.matrixWorld).invert()), | ||
.applyMatrix4(invertedMatrixHelper.copy(intersection.object.matrixWorld).invert()), | ||
}); | ||
@@ -119,0 +117,0 @@ } |
@@ -10,3 +10,4 @@ import { Plane, Intersection as ThreeIntersection, Object3D, Vector3, Ray, Quaternion } from 'three'; | ||
*/ | ||
export declare function getDominantIntersectionIndex<T extends ThreeIntersection>(i1: T | undefined, pointerEventsOrder1: number | undefined, i2: Array<T>, pointerEventsOrder2: number | undefined, { customSort: compare }?: IntersectionOptions): number | undefined; | ||
export declare function getDominantIntersectionIndex<T extends ThreeIntersection>(intersections: Array<T>, pointerEventsOrders: Array<number | undefined>, { customSort: compare }?: IntersectionOptions, filter?: (intersection: ThreeIntersection) => boolean): number | undefined; | ||
export declare function voidObjectIntersectionFromRay(scene: Object3D, ray: Ray, getDetails: (distanceOnRay: number) => Intersection['details'], pointerPosition: Vector3, pointerQuaternion: Quaternion, addToDistance?: number): Intersection; | ||
export declare function pushTimes<T>(target: Array<T>, value: T, times: number): void; |
@@ -76,3 +76,3 @@ import { Vector3 } from 'three'; | ||
function filterAndInteresct({ intersector, options }, object, pointerEvents, pointerEventsType, pointerEventsOrder) { | ||
if (options.filter != null && !options.filter(object, pointerEvents, pointerEventsType, pointerEventsOrder)) { | ||
if (options.filter?.(object, pointerEvents, pointerEventsType, pointerEventsOrder) === false) { | ||
return; | ||
@@ -86,10 +86,17 @@ } | ||
*/ | ||
export function getDominantIntersectionIndex(i1, pointerEventsOrder1, i2, pointerEventsOrder2, { customSort: compare = defaultSort } = {}) { | ||
export function getDominantIntersectionIndex(intersections, pointerEventsOrders, { customSort: compare = defaultSort } = {}, filter) { | ||
let intersection = undefined; | ||
let pointerEventsOrder = undefined; | ||
let index = undefined; | ||
const length = i2.length; | ||
const length = intersections.length; | ||
for (let i = 0; i < length; i++) { | ||
const intersection = i2[i]; | ||
if (i1 == null || compare(i1, pointerEventsOrder1, intersection, pointerEventsOrder2) > 0) { | ||
i1 = intersection; | ||
const newIntersection = intersections[i]; | ||
if (filter?.(newIntersection) === false) { | ||
continue; | ||
} | ||
const newPointerEventsOrder = pointerEventsOrders[i]; | ||
if (intersection == null || compare(newIntersection, newPointerEventsOrder, intersection, pointerEventsOrder) < 0) { | ||
index = i; | ||
intersection = newIntersection; | ||
pointerEventsOrder = newPointerEventsOrder; | ||
} | ||
@@ -125,1 +132,7 @@ } | ||
} | ||
export function pushTimes(target, value, times) { | ||
while (times > 0) { | ||
target.push(value); | ||
--times; | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Object3D, } from 'three'; | ||
import { Object3D } from 'three'; | ||
import { PointerEvent, WheelEvent, emitPointerEvent } from './event.js'; | ||
@@ -3,0 +3,0 @@ import { intersectPointerEventTargets } from './intersections/utils.js'; |
@@ -5,3 +5,3 @@ { | ||
"license": "SEE LICENSE IN LICENSE", | ||
"version": "6.2.19", | ||
"version": "6.3.0", | ||
"homepage": "https://github.com/pmndrs/xr", | ||
@@ -8,0 +8,0 @@ "author": "Bela Bohlender", |
96420
2289