-
Notifications
You must be signed in to change notification settings - Fork 46
/
picking-interaction.ts
73 lines (66 loc) · 2.42 KB
/
picking-interaction.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { Ticker, UPDATE_PRIORITY } from "@pixi/ticker"
import { IRendererPlugin, Renderer } from "@pixi/core"
import { Point } from "@pixi/math"
import { PickingMap } from "./picking-map"
import { PickingHitArea } from "./picking-hitarea"
import { Compatibility } from "../compatibility/compatibility"
/**
* Manages the picking hit areas by keeping track on which hit areas needs to
* be checked for interaction. Renders the hit area meshes to a texture which
* is then used to map a mesh to a x/y coordinate. The picking manager is
* registered as a renderer plugin.
*/
export class PickingInteraction implements IRendererPlugin {
private _map: PickingMap
private _hitAreas: PickingHitArea[] = []
/**
* Creates a new picking manager using the specified renderer.
* @param renderer The renderer to use.
*/
constructor(public renderer: Renderer) {
this._map = new PickingMap(this.renderer, 128)
Ticker.shared.add(this._update, this, UPDATE_PRIORITY.LOW)
if (!PickingInteraction.main) {
PickingInteraction.main = this
}
}
/** The main picking interaction which is used by default. */
static main: PickingInteraction
private _update() {
if (!this.renderer.plugins) {
return
}
// Because of how PixiJS interaction works and the design of the picking,
// the "hitTest" function needs to be called. Otherwise, in some
// circumstances; the picking is affected by in which order the interaction
// object was added to the heirarchy.
let interaction = Compatibility.getInteractionPlugin(this.renderer)
if (interaction) {
interaction.hitTest(new Point(0, 0))
}
if (this._hitAreas.length > 0) {
this._map.resizeToAspect()
this._map.update(this._hitAreas); this._hitAreas = []
}
}
destroy() {
if (this === PickingInteraction.main) {
// @ts-ignore It's ok, main picking interaction was destroyed.
PickingInteraction.main = undefined
}
Ticker.shared.remove(this._update, this)
}
/**
* Hit tests a area using the specified x/y coordinates.
* @param x The x coordinate.
* @param y The y coordinate.
* @param hitArea The hit area to test.
*/
containsHitArea(x: number, y: number, hitArea: PickingHitArea) {
if (this._hitAreas.indexOf(hitArea) < 0) {
this._hitAreas.push(hitArea)
}
return this._map.containsId(x, y, hitArea.id)
}
}
Compatibility.installRendererPlugin("picking", PickingInteraction)