lunchboxjs 0.2.1001-beta.0 → 0.2.1001-beta.1
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/README.md +0 -47
- package/dist/lunchboxjs.js +292 -347
- package/dist/lunchboxjs.min.js +1 -1
- package/dist/lunchboxjs.module.js +292 -342
- package/package.json +3 -2
- package/src/components/LunchboxEventHandlers.tsx +239 -0
- package/src/components/LunchboxWrapper/LunchboxWrapper.tsx +7 -6
- package/src/components/autoGeneratedComponents.ts +1 -1
- package/src/components/index.ts +2 -2
- package/src/core/createNode.ts +1 -1
- package/src/core/extend.ts +1 -1
- package/src/core/instantiateThreeObject/index.ts +1 -1
- package/src/core/instantiateThreeObject/processProps.ts +1 -1
- package/src/core/interaction.ts +55 -0
- package/src/core/minidom.ts +1 -1
- package/src/core/update.ts +2 -30
- package/src/core/updateObjectProp.ts +5 -14
- package/src/index.ts +12 -3
- package/src/keys.ts +1 -0
- package/src/nodeOps/index.ts +70 -57
- package/src/types.ts +0 -8
- package/src/components/catalogue.ts +0 -3
- package/src/core/interaction/index.ts +0 -102
- package/src/core/interaction/input.ts +0 -4
- package/src/core/interaction/interactables.ts +0 -14
- package/src/core/interaction/setupAutoRaycaster.ts +0 -232
package/src/nodeOps/index.ts
CHANGED
|
@@ -1,70 +1,83 @@
|
|
|
1
|
-
import { RendererOptions } from 'vue'
|
|
1
|
+
import { RendererOptions, ref } from 'vue'
|
|
2
2
|
import { createElement } from './createElement'
|
|
3
3
|
import { insert } from './insert'
|
|
4
4
|
import { remove } from './remove'
|
|
5
5
|
import { isLunchboxDomComponent, isLunchboxRootNode } from '../utils'
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
MiniDom,
|
|
10
|
-
updateObjectProp,
|
|
11
|
-
} from '../core'
|
|
12
|
-
import { Lunch } from '..'
|
|
6
|
+
import { createCommentNode, createTextNode, updateObjectProp } from '../core'
|
|
7
|
+
import type { MiniDom } from '../core'
|
|
8
|
+
import type { Lunch } from '..'
|
|
13
9
|
|
|
14
10
|
/*
|
|
15
11
|
Elements are `create`d from the outside in, then `insert`ed from the inside out.
|
|
16
12
|
*/
|
|
17
13
|
|
|
18
|
-
export const
|
|
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
|
-
|
|
14
|
+
export const createNodeOps = () => {
|
|
15
|
+
// APP-LEVEL GLOBALS
|
|
16
|
+
// ====================
|
|
17
|
+
// These need to exist at the app level in a place where the node ops can access them.
|
|
18
|
+
// It'd be better to set these via `app.provide` at app creation, but the node ops need access
|
|
19
|
+
// to these values before the app is instantiated, so this is the next-best place for them to exist.
|
|
20
|
+
const interactables = ref([] as Lunch.Node[])
|
|
21
|
+
|
|
22
|
+
// NODE OPS
|
|
23
|
+
// ====================
|
|
24
|
+
const nodeOps: RendererOptions<
|
|
25
|
+
MiniDom.RendererBaseNode,
|
|
26
|
+
MiniDom.RendererBaseNode
|
|
27
|
+
> = {
|
|
28
|
+
createElement,
|
|
29
|
+
createText(text) {
|
|
30
|
+
return createTextNode({ text })
|
|
31
|
+
},
|
|
32
|
+
createComment(text) {
|
|
33
|
+
return createCommentNode({ text })
|
|
34
|
+
},
|
|
35
|
+
insert,
|
|
36
|
+
nextSibling(node) {
|
|
37
|
+
const result = node.nextSibling
|
|
38
|
+
if (!result) return null
|
|
39
|
+
return result as MiniDom.RendererBaseNode
|
|
40
|
+
},
|
|
41
|
+
parentNode(node) {
|
|
42
|
+
const result = node.parentNode
|
|
43
|
+
if (!result) return null
|
|
44
|
+
return result as MiniDom.RendererBaseNode
|
|
45
|
+
},
|
|
46
|
+
patchProp(node, key, prevValue, nextValue) {
|
|
47
|
+
if (isLunchboxDomComponent(node)) {
|
|
48
|
+
// handle DOM node
|
|
49
|
+
if (key === 'style') {
|
|
50
|
+
// special handling for style
|
|
51
|
+
Object.keys(nextValue).forEach((k) => {
|
|
52
|
+
;(node.domElement.style as any)[k] = nextValue[k]
|
|
53
|
+
})
|
|
54
|
+
} else {
|
|
55
|
+
node.domElement.setAttribute(key, nextValue)
|
|
56
|
+
}
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ignore if root node, or Lunchbox internal prop
|
|
61
|
+
if (isLunchboxRootNode(node) || key.startsWith('$')) {
|
|
62
|
+
return
|
|
51
63
|
}
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
// otherwise, update prop
|
|
66
|
+
updateObjectProp({
|
|
67
|
+
node: node as Lunch.Node,
|
|
68
|
+
key,
|
|
69
|
+
interactables,
|
|
70
|
+
value: nextValue,
|
|
71
|
+
})
|
|
72
|
+
},
|
|
73
|
+
remove,
|
|
74
|
+
setElementText() {
|
|
75
|
+
// noop
|
|
76
|
+
},
|
|
77
|
+
setText() {
|
|
78
|
+
// noop
|
|
79
|
+
},
|
|
80
|
+
}
|
|
59
81
|
|
|
60
|
-
|
|
61
|
-
updateObjectProp({ node: node as Lunch.Node, key, value: nextValue })
|
|
62
|
-
},
|
|
63
|
-
remove,
|
|
64
|
-
setElementText() {
|
|
65
|
-
// noop
|
|
66
|
-
},
|
|
67
|
-
setText() {
|
|
68
|
-
// noop
|
|
69
|
-
},
|
|
82
|
+
return { nodeOps, interactables }
|
|
70
83
|
}
|
package/src/types.ts
CHANGED
|
@@ -36,10 +36,6 @@ export declare namespace Lunch {
|
|
|
36
36
|
update: UpdateCallback
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
// type AppGlobals = {
|
|
40
|
-
// /** Device pixel resolution */
|
|
41
|
-
// dpr: number
|
|
42
|
-
// }
|
|
43
39
|
type AppGlobals = App['config']['globalProperties']['lunchbox']
|
|
44
40
|
|
|
45
41
|
type AppGlobalsUpdate = (newValue: Partial<AppGlobals>) => void
|
|
@@ -159,10 +155,6 @@ export declare namespace Lunch {
|
|
|
159
155
|
renderer?: THREE.Renderer | null
|
|
160
156
|
camera?: THREE.Camera | null
|
|
161
157
|
updateSource?: WatchSource | null
|
|
162
|
-
|
|
163
|
-
// sceneNode: Node<THREE.Scene> | null
|
|
164
|
-
// rendererNode: Node<THREE.Renderer> | null
|
|
165
|
-
// cameraNode: Node<THREE.Camera> | null
|
|
166
158
|
}
|
|
167
159
|
|
|
168
160
|
/** Universally unique identifier. */
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { watch } from 'vue'
|
|
2
|
-
import {
|
|
3
|
-
addInteractable,
|
|
4
|
-
interactables,
|
|
5
|
-
removeInteractable,
|
|
6
|
-
} from './interactables'
|
|
7
|
-
// import { ensuredRaycaster } from '..'
|
|
8
|
-
import { inputActive } from './input'
|
|
9
|
-
import { currentIntersections } from '.'
|
|
10
|
-
import { Lunch } from '../..'
|
|
11
|
-
|
|
12
|
-
export * from './input'
|
|
13
|
-
export * from './interactables'
|
|
14
|
-
export * from './setupAutoRaycaster'
|
|
15
|
-
|
|
16
|
-
/** Add an event listener to the given node. Also creates the event teardown function and any necessary raycaster/interaction dictionary updates. */
|
|
17
|
-
export function addEventListener({
|
|
18
|
-
node,
|
|
19
|
-
key,
|
|
20
|
-
value,
|
|
21
|
-
}: {
|
|
22
|
-
node: Lunch.Node
|
|
23
|
-
key: Lunch.EventKey
|
|
24
|
-
value: Lunch.EventCallback
|
|
25
|
-
}) {
|
|
26
|
-
// create new records for this key if needed
|
|
27
|
-
if (!node.eventListeners[key]) {
|
|
28
|
-
node.eventListeners[key] = []
|
|
29
|
-
}
|
|
30
|
-
if (!node.eventListenerRemoveFunctions[key]) {
|
|
31
|
-
node.eventListenerRemoveFunctions[key] = []
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// add event listener
|
|
35
|
-
node.eventListeners[key].push(value)
|
|
36
|
-
|
|
37
|
-
// if we need it, let's get/create the main raycaster
|
|
38
|
-
if (interactionsRequiringRaycaster.includes(key)) {
|
|
39
|
-
// we're not using `v` here, we're just making sure the raycaster has been created
|
|
40
|
-
// TODO: is this necessary?
|
|
41
|
-
// const v = ensuredRaycaster.value
|
|
42
|
-
|
|
43
|
-
if (node.instance && !interactables.includes(node)) {
|
|
44
|
-
addInteractable(node)
|
|
45
|
-
node.eventListenerRemoveFunctions[key].push(() =>
|
|
46
|
-
removeInteractable(node)
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// register click, pointerdown, pointerup
|
|
52
|
-
if (key === 'onClick' || key === 'onPointerDown' || key === 'onPointerUp') {
|
|
53
|
-
const stop = watch(
|
|
54
|
-
() => inputActive.value,
|
|
55
|
-
(isDown) => {
|
|
56
|
-
const idx = currentIntersections
|
|
57
|
-
.map((v) => v.element)
|
|
58
|
-
.findIndex(
|
|
59
|
-
(v) =>
|
|
60
|
-
v.instance &&
|
|
61
|
-
v.instance.uuid === node.instance?.uuid
|
|
62
|
-
)
|
|
63
|
-
if (idx !== -1) {
|
|
64
|
-
if (
|
|
65
|
-
isDown &&
|
|
66
|
-
(key === 'onClick' || key === 'onPointerDown')
|
|
67
|
-
) {
|
|
68
|
-
node.eventListeners[key].forEach((func) => {
|
|
69
|
-
func({
|
|
70
|
-
intersection:
|
|
71
|
-
currentIntersections[idx].intersection,
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
} else if (!isDown && key === 'onPointerUp') {
|
|
75
|
-
node.eventListeners[key].forEach((func) => {
|
|
76
|
-
func({
|
|
77
|
-
intersection:
|
|
78
|
-
currentIntersections[idx].intersection,
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
node.eventListenerRemoveFunctions[key].push(stop)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return node
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const interactionsRequiringRaycaster = [
|
|
93
|
-
'onClick',
|
|
94
|
-
'onPointerUp',
|
|
95
|
-
'onPointerDown',
|
|
96
|
-
'onPointerOver',
|
|
97
|
-
'onPointerOut',
|
|
98
|
-
'onPointerEnter',
|
|
99
|
-
'onPointerLeave',
|
|
100
|
-
'onPointerMove',
|
|
101
|
-
// 'onPointerMissed',
|
|
102
|
-
]
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Lunch } from '../..'
|
|
2
|
-
|
|
3
|
-
export const interactables: Array<Lunch.Node> = []
|
|
4
|
-
|
|
5
|
-
export const addInteractable = (target: Lunch.Node) => {
|
|
6
|
-
interactables.push(target)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const removeInteractable = (target: Lunch.Node) => {
|
|
10
|
-
const idx = interactables.indexOf(target)
|
|
11
|
-
if (idx !== -1) {
|
|
12
|
-
interactables.splice(idx, 1)
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
// import { interactables } from '.'
|
|
2
|
-
// import {
|
|
3
|
-
// ensuredCamera,
|
|
4
|
-
// // ensuredRaycaster,
|
|
5
|
-
// ensureRenderer,
|
|
6
|
-
// onBeforeRender,
|
|
7
|
-
// } from '..'
|
|
8
|
-
import {
|
|
9
|
-
// globals,
|
|
10
|
-
Lunch,
|
|
11
|
-
useGlobals,
|
|
12
|
-
} from '../../'
|
|
13
|
-
import { ref, watch, WatchStopHandle } from 'vue'
|
|
14
|
-
import { inputActive } from './input'
|
|
15
|
-
import { Intersection } from 'three'
|
|
16
|
-
|
|
17
|
-
// let mouseMoveListener: (event: MouseEvent) => void
|
|
18
|
-
// let mouseDownListener: (event: MouseEvent) => void
|
|
19
|
-
// let mouseUpListener: (event: MouseEvent) => void
|
|
20
|
-
|
|
21
|
-
export const mousePos = ref({ x: Infinity, y: Infinity })
|
|
22
|
-
// let autoRaycasterEventsInitialized = false
|
|
23
|
-
|
|
24
|
-
// let frameID: number
|
|
25
|
-
|
|
26
|
-
// export const setupAutoRaycaster = (node: Lunch.Node<THREE.Raycaster>) => {
|
|
27
|
-
// const instance = node.instance
|
|
28
|
-
|
|
29
|
-
// if (!instance) return
|
|
30
|
-
|
|
31
|
-
// // TODO: inject doesn't work here. replace this raycaster with a component so we can
|
|
32
|
-
// // `inject` in `setup`?
|
|
33
|
-
// const appLevelGlobals = { dpr: window.devicePixelRatio } //useGlobals()
|
|
34
|
-
|
|
35
|
-
// // add mouse events once renderer is ready
|
|
36
|
-
// let stopWatcher: WatchStopHandle | null = null
|
|
37
|
-
// stopWatcher = watch(
|
|
38
|
-
// () => ensureRenderer.value,
|
|
39
|
-
// (renderer) => {
|
|
40
|
-
// // make sure renderer exists
|
|
41
|
-
// if (!renderer?.instance) return
|
|
42
|
-
|
|
43
|
-
// // cancel early if autoraycaster exists
|
|
44
|
-
// if (autoRaycasterEventsInitialized) {
|
|
45
|
-
// if (stopWatcher) stopWatcher()
|
|
46
|
-
// return
|
|
47
|
-
// }
|
|
48
|
-
|
|
49
|
-
// // create mouse events
|
|
50
|
-
// mouseMoveListener = (evt) => {
|
|
51
|
-
// const screenWidth =
|
|
52
|
-
// (renderer.instance!.domElement.width ?? 1) /
|
|
53
|
-
// appLevelGlobals.dpr
|
|
54
|
-
// const screenHeight =
|
|
55
|
-
// (renderer.instance!.domElement.height ?? 1) /
|
|
56
|
-
// appLevelGlobals.dpr
|
|
57
|
-
|
|
58
|
-
// mousePos.value.x = (evt.offsetX / screenWidth) * 2 - 1
|
|
59
|
-
// mousePos.value.y = -(evt.offsetY / screenHeight) * 2 + 1
|
|
60
|
-
// }
|
|
61
|
-
// mouseDownListener = () => (inputActive.value = true)
|
|
62
|
-
// mouseUpListener = () => (inputActive.value = false)
|
|
63
|
-
|
|
64
|
-
// // add mouse events
|
|
65
|
-
// renderer.instance.domElement.addEventListener(
|
|
66
|
-
// 'mousemove',
|
|
67
|
-
// mouseMoveListener
|
|
68
|
-
// )
|
|
69
|
-
// renderer.instance.domElement.addEventListener(
|
|
70
|
-
// 'mousedown',
|
|
71
|
-
// mouseDownListener
|
|
72
|
-
// )
|
|
73
|
-
// renderer.instance.domElement.addEventListener(
|
|
74
|
-
// 'mouseup',
|
|
75
|
-
// mouseUpListener
|
|
76
|
-
// )
|
|
77
|
-
|
|
78
|
-
// // TODO: add touch events
|
|
79
|
-
|
|
80
|
-
// // process mouse events asynchronously, whenever the mouse state changes
|
|
81
|
-
// watch(
|
|
82
|
-
// () => [inputActive.value, mousePos.value.x, mousePos.value.y],
|
|
83
|
-
// () => {
|
|
84
|
-
// if (frameID) cancelAnimationFrame(frameID)
|
|
85
|
-
// frameID = requestAnimationFrame(() => {
|
|
86
|
-
// autoRaycasterBeforeRender()
|
|
87
|
-
// })
|
|
88
|
-
// }
|
|
89
|
-
// )
|
|
90
|
-
|
|
91
|
-
// // mark complete
|
|
92
|
-
// autoRaycasterEventsInitialized = true
|
|
93
|
-
|
|
94
|
-
// // cancel setup watcher
|
|
95
|
-
// if (stopWatcher) {
|
|
96
|
-
// stopWatcher()
|
|
97
|
-
// }
|
|
98
|
-
// },
|
|
99
|
-
// { immediate: true }
|
|
100
|
-
// )
|
|
101
|
-
// }
|
|
102
|
-
|
|
103
|
-
// AUTO-RAYCASTER CALLBACK
|
|
104
|
-
// ====================
|
|
105
|
-
export let currentIntersections: Array<{
|
|
106
|
-
element: Lunch.Node
|
|
107
|
-
intersection: Intersection<THREE.Object3D>
|
|
108
|
-
}> = []
|
|
109
|
-
|
|
110
|
-
// const autoRaycasterBeforeRender = () => {
|
|
111
|
-
// // setup
|
|
112
|
-
// const raycaster = ensuredRaycaster.value?.instance
|
|
113
|
-
// const camera = ensuredCamera.value?.instance
|
|
114
|
-
// if (!raycaster || !camera) return
|
|
115
|
-
|
|
116
|
-
// raycaster.setFromCamera(globals.mousePos.value, camera)
|
|
117
|
-
// const intersections = raycaster.intersectObjects(
|
|
118
|
-
// interactables.map((v) => v.instance as any as THREE.Object3D)
|
|
119
|
-
// )
|
|
120
|
-
|
|
121
|
-
// let enterValues: Array<Intersection<THREE.Object3D>> = [],
|
|
122
|
-
// sameValues: Array<Intersection<THREE.Object3D>> = [],
|
|
123
|
-
// leaveValues: Array<Intersection<THREE.Object3D>> = [],
|
|
124
|
-
// entering: Array<{
|
|
125
|
-
// element: Lunch.Node
|
|
126
|
-
// intersection: Intersection<THREE.Object3D>
|
|
127
|
-
// }> = [],
|
|
128
|
-
// staying: Array<{
|
|
129
|
-
// element: Lunch.Node
|
|
130
|
-
// intersection: Intersection<THREE.Object3D>
|
|
131
|
-
// }> = []
|
|
132
|
-
|
|
133
|
-
// // intersection arrays
|
|
134
|
-
// leaveValues = currentIntersections.map((v) => v.intersection)
|
|
135
|
-
|
|
136
|
-
// // element arrays
|
|
137
|
-
// intersections?.forEach((intersection) => {
|
|
138
|
-
// const currentIdx = currentIntersections.findIndex(
|
|
139
|
-
// (v) => v.intersection.object === intersection.object
|
|
140
|
-
// )
|
|
141
|
-
// if (currentIdx === -1) {
|
|
142
|
-
// // new intersection
|
|
143
|
-
// enterValues.push(intersection)
|
|
144
|
-
|
|
145
|
-
// const found = interactables.find(
|
|
146
|
-
// (v) => v.instance?.uuid === intersection.object.uuid
|
|
147
|
-
// )
|
|
148
|
-
// if (found) {
|
|
149
|
-
// entering.push({ element: found, intersection })
|
|
150
|
-
// }
|
|
151
|
-
// } else {
|
|
152
|
-
// // existing intersection
|
|
153
|
-
// sameValues.push(intersection)
|
|
154
|
-
|
|
155
|
-
// const found = interactables.find(
|
|
156
|
-
// (v) => v.instance?.uuid === intersection.object.uuid
|
|
157
|
-
// )
|
|
158
|
-
// if (found) {
|
|
159
|
-
// staying.push({ element: found, intersection })
|
|
160
|
-
// }
|
|
161
|
-
// }
|
|
162
|
-
// // this is a current intersection, so it won't be in our `leave` array
|
|
163
|
-
// const leaveIdx = leaveValues.findIndex(
|
|
164
|
-
// (v) => v.object.uuid === intersection.object.uuid
|
|
165
|
-
// )
|
|
166
|
-
// if (leaveIdx !== -1) {
|
|
167
|
-
// leaveValues.splice(leaveIdx, 1)
|
|
168
|
-
// }
|
|
169
|
-
// })
|
|
170
|
-
|
|
171
|
-
// const leaving: Array<{
|
|
172
|
-
// element: Lunch.Node
|
|
173
|
-
// intersection: Intersection<THREE.Object3D>
|
|
174
|
-
// }> = leaveValues.map((intersection) => {
|
|
175
|
-
// return {
|
|
176
|
-
// element: interactables.find(
|
|
177
|
-
// (interactable) =>
|
|
178
|
-
// interactable.instance?.uuid === intersection.object.uuid
|
|
179
|
-
// ) as any as Lunch.Node,
|
|
180
|
-
// intersection,
|
|
181
|
-
// }
|
|
182
|
-
// })
|
|
183
|
-
|
|
184
|
-
// // new interactions
|
|
185
|
-
// entering.forEach(({ element, intersection }) => {
|
|
186
|
-
// fireEventsFromIntersections({
|
|
187
|
-
// element,
|
|
188
|
-
// eventKeys: ['onPointerEnter'],
|
|
189
|
-
// intersection,
|
|
190
|
-
// })
|
|
191
|
-
// })
|
|
192
|
-
|
|
193
|
-
// // unchanged interactions
|
|
194
|
-
// staying.forEach(({ element, intersection }) => {
|
|
195
|
-
// const eventKeys: Array<Lunch.EventKey> = [
|
|
196
|
-
// 'onPointerOver',
|
|
197
|
-
// 'onPointerMove',
|
|
198
|
-
// ]
|
|
199
|
-
// fireEventsFromIntersections({ element, eventKeys, intersection })
|
|
200
|
-
// })
|
|
201
|
-
|
|
202
|
-
// // exited interactions
|
|
203
|
-
// leaving.forEach(({ element, intersection }) => {
|
|
204
|
-
// const eventKeys: Array<Lunch.EventKey> = [
|
|
205
|
-
// 'onPointerLeave',
|
|
206
|
-
// 'onPointerOut',
|
|
207
|
-
// ]
|
|
208
|
-
// fireEventsFromIntersections({ element, eventKeys, intersection })
|
|
209
|
-
// })
|
|
210
|
-
|
|
211
|
-
// currentIntersections = ([] as any).concat(entering, staying)
|
|
212
|
-
// }
|
|
213
|
-
|
|
214
|
-
// utility function for firing multiple callbacks and multiple events on a Lunchbox.Element
|
|
215
|
-
// const fireEventsFromIntersections = ({
|
|
216
|
-
// element,
|
|
217
|
-
// eventKeys,
|
|
218
|
-
// intersection,
|
|
219
|
-
// }: {
|
|
220
|
-
// element: Lunch.Node
|
|
221
|
-
// eventKeys: Array<Lunch.EventKey>
|
|
222
|
-
// intersection: Intersection<THREE.Object3D>
|
|
223
|
-
// }) => {
|
|
224
|
-
// if (!element) return
|
|
225
|
-
// eventKeys.forEach((eventKey) => {
|
|
226
|
-
// if (element.eventListeners[eventKey]) {
|
|
227
|
-
// element.eventListeners[eventKey].forEach((cb) => {
|
|
228
|
-
// cb({ intersection })
|
|
229
|
-
// })
|
|
230
|
-
// }
|
|
231
|
-
// })
|
|
232
|
-
// }
|