@px-petals/roku.motion-web 0.0.0-stage → 1.1.0
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/LICENSE +201 -0
- package/audio/audio.cues.js +27 -0
- package/audio/audio.js +259 -0
- package/bands/bands.js +392 -0
- package/bundle/bundle.fonts.js +55 -0
- package/bundle/bundle.js +131 -0
- package/focus/focus.direction.js +46 -0
- package/focus/focus.dom.js +158 -0
- package/focus/focus.js +277 -0
- package/focus/focus.tree.js +146 -0
- package/hit/hit.geometry.js +113 -0
- package/hit/hit.js +129 -0
- package/list/list.flex.js +181 -0
- package/list/list.items.js +80 -0
- package/list/list.js +518 -0
- package/lottie/lottie.js +124 -0
- package/lottie/lottie.layers.js +416 -0
- package/lottie/lottie.paint.js +238 -0
- package/lottie/lottie.paths.js +474 -0
- package/lottie/lottie.props.js +265 -0
- package/lottie/lottie.shapes.js +259 -0
- package/mixer/mixer.js +307 -0
- package/mixer/mixer.mix.js +107 -0
- package/mixer/mixer.stage.js +431 -0
- package/motion/motion.convert.js +404 -0
- package/motion/motion.flow.js +421 -0
- package/motion/motion.keys.js +150 -0
- package/motion/motion.machine.js +382 -0
- package/motion/motion.nested.js +345 -0
- package/motion/motion.values.js +368 -0
- package/motion.js +1155 -0
- package/package.json +47 -4
- package/player/overlay/overlay.js +325 -0
- package/player/overlay/overlay.layout.js +208 -0
- package/player/player.fit.js +101 -0
- package/player/player.js +421 -0
- package/player/player.raster.js +127 -0
- package/pointer/pointer.js +292 -0
- package/readme.md +345 -0
- package/script/luau/lib/base/base.js +202 -0
- package/script/luau/lib/base/base.table.js +189 -0
- package/script/luau/lib/lib.args.js +152 -0
- package/script/luau/lib/lib.js +23 -0
- package/script/luau/lib/math/math.bit32.js +144 -0
- package/script/luau/lib/math/math.js +288 -0
- package/script/luau/lib/math/math.vector.js +125 -0
- package/script/luau/lib/string/string.format.js +143 -0
- package/script/luau/lib/string/string.js +160 -0
- package/script/luau/lib/string/string.pattern.js +505 -0
- package/script/luau/load/load.js +362 -0
- package/script/luau/load/load.ops.js +79 -0
- package/script/luau/luau.convert.js +259 -0
- package/script/luau/luau.js +132 -0
- package/script/luau/luau.md +111 -0
- package/script/luau/vm/vm.js +167 -0
- package/script/luau/vm/vm.meta.js +401 -0
- package/script/luau/vm/vm.num.js +236 -0
- package/script/luau/vm/vm.run.js +842 -0
- package/script/luau/vm/vm.value.js +406 -0
- package/script/play/play.js +199 -0
- package/script/play/play.objects.js +295 -0
- package/script/play/play.scope.js +91 -0
- package/script/rive/api/api.statics.js +31 -0
- package/script/rive/api/api.type.js +188 -0
- package/script/rive/api/artboard/artboard.js +89 -0
- package/script/rive/api/assets/assets.js +72 -0
- package/script/rive/api/data/data.value.js +99 -0
- package/script/rive/api/draw/draw.contours.js +163 -0
- package/script/rive/api/draw/draw.measure.js +196 -0
- package/script/rive/api/draw/draw.paint.js +235 -0
- package/script/rive/api/draw/draw.path.js +153 -0
- package/script/rive/api/draw/draw.renderer.js +117 -0
- package/script/rive/api/math/math.color.js +96 -0
- package/script/rive/api/math/math.mat2d.js +180 -0
- package/script/rive/api/math/math.vector.js +121 -0
- package/script/rive/api/media/media.audio.js +113 -0
- package/script/rive/api/media/media.draw.js +73 -0
- package/script/rive/api/media/media.image.js +61 -0
- package/script/rive/api/media/media.mesh.js +50 -0
- package/script/rive/api/pointer/pointer.event.js +64 -0
- package/script/rive/api/pointer/pointer.route.js +69 -0
- package/script/rive/api/text/text.font.js +129 -0
- package/script/rive/api/text/text.js +278 -0
- package/script/rive/api/text/text.layout.js +259 -0
- package/script/rive/context/context.js +76 -0
- package/script/rive/context/context.memory.js +196 -0
- package/script/rive/context/context.viewmodel.js +302 -0
- package/script/rive/context/lists/lists.js +160 -0
- package/script/rive/context/lists/lists.values.js +281 -0
- package/script/rive/host/host.globals.js +44 -0
- package/script/rive/host/host.js +533 -0
- package/script/rive/host/host.node.js +45 -0
- package/script/rive/rive.js +23 -0
- package/script/rive/rive.md +180 -0
- package/script/script.js +11 -0
- package/skin/skin.deform.js +514 -0
- package/skin/skin.ik.js +260 -0
- package/skin/skin.js +297 -0
- package/README.md +0 -3
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pointer on the canvas: mouse, touch and pen events become the pointer
|
|
3
|
+
* interactions a bundle's listeners answer (down, up, enter, exit, move,
|
|
4
|
+
* click), each hit-tested against the shape or group the listener targets.
|
|
5
|
+
*
|
|
6
|
+
* - A target is hovered while the pointer is inside its geometry in the last
|
|
7
|
+
* drawn frame (`hit/`), so enter and exit follow a moving shape as well as
|
|
8
|
+
* a moving pointer.
|
|
9
|
+
* - A listener with no target watches the whole canvas: it enters when the
|
|
10
|
+
* pointer comes onto the canvas and exits when it leaves.
|
|
11
|
+
* - A click is a down and an up on the same target. Clicks on the canvas
|
|
12
|
+
* itself (the `click` event) belong to the listeners with no target, which
|
|
13
|
+
* motion.js forwards.
|
|
14
|
+
*
|
|
15
|
+
* Events: `pointer*` where the browser has them (they cover mouse, touch and
|
|
16
|
+
* pen); otherwise `mouse*` and `touch*`, ignoring the mouse events a touch
|
|
17
|
+
* makes up afterwards.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** @import { Hits } from '../hit/hit.js' */
|
|
21
|
+
|
|
22
|
+
/** A mouse event this soon after a touch is the browser's own imitation of it */
|
|
23
|
+
const TOUCH_MOUSE_MS = 800
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {object} PointerOptions
|
|
27
|
+
* @property {() => Hits | null} hits the geometry the last frame drew; null while it is not vector
|
|
28
|
+
* @property {(type: string, target: string) => void} fire runs a pointer interaction; target "" for the listeners without one
|
|
29
|
+
* @property {boolean} clicks whether a click fires Click interactions
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {HTMLCanvasElement} canvas
|
|
34
|
+
* @param {PointerOptions} options
|
|
35
|
+
*/
|
|
36
|
+
export function createPointer(canvas, options) {
|
|
37
|
+
/** @type {Record<string, string[]>} target → interaction types, as the machine lists them */
|
|
38
|
+
let targets = {}
|
|
39
|
+
/** @type {Record<string, boolean>} */
|
|
40
|
+
let inside = {}
|
|
41
|
+
/** @type {Record<string, boolean>} */
|
|
42
|
+
let pressed = {}
|
|
43
|
+
let lastTouch = 0
|
|
44
|
+
let isBound = false
|
|
45
|
+
/** @type {{ name: string, listener: (event: any) => void }[]} */
|
|
46
|
+
const bound = []
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {string} target
|
|
50
|
+
* @param {string} type
|
|
51
|
+
* @returns {boolean}
|
|
52
|
+
*/
|
|
53
|
+
const listensTo = (target, type) => !!targets[target] && targets[target].indexOf(type) >= 0
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {string[]} types
|
|
57
|
+
* @returns {boolean} whether any target listens to one of these
|
|
58
|
+
*/
|
|
59
|
+
const hasAny = (types) => {
|
|
60
|
+
for (const target in targets) for (let n = 0; n < types.length; n++) if (listensTo(target, types[n])) return true
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {string} target
|
|
66
|
+
* @param {number} x
|
|
67
|
+
* @param {number} y
|
|
68
|
+
* @returns {boolean} whether the pointer is on the target
|
|
69
|
+
*/
|
|
70
|
+
function isOn(target, x, y) {
|
|
71
|
+
if (target === '') return true
|
|
72
|
+
const hits = options.hits()
|
|
73
|
+
return !!hits && hits.test(target, x, y)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Takes the interactions each target listens to and starts watching for the pointer, or stops.
|
|
78
|
+
*
|
|
79
|
+
* @param {Record<string, string[]>} next the machine's `pointerTargets`
|
|
80
|
+
*/
|
|
81
|
+
function listen(next) {
|
|
82
|
+
// what is watched again keeps where the pointer is on it: rows that come and go do not end a press on the others
|
|
83
|
+
/** @type {Record<string, boolean>} */
|
|
84
|
+
const keptInside = {}
|
|
85
|
+
/** @type {Record<string, boolean>} */
|
|
86
|
+
const keptPressed = {}
|
|
87
|
+
for (const name in next) {
|
|
88
|
+
if (!targets[name]) continue
|
|
89
|
+
keptInside[name] = inside[name]
|
|
90
|
+
keptPressed[name] = pressed[name]
|
|
91
|
+
}
|
|
92
|
+
targets = next
|
|
93
|
+
inside = keptInside
|
|
94
|
+
pressed = keptPressed
|
|
95
|
+
const wanted = hasAny([ 'PointerDown', 'PointerUp', 'PointerEnter', 'PointerExit', 'PointerMove' ]) || (options.clicks && hasAnyTargeted('Click'))
|
|
96
|
+
if (wanted && !isBound) bind()
|
|
97
|
+
else if (!wanted && isBound) unbind()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {string} type
|
|
102
|
+
* @returns {boolean} whether a listener on a target (not the whole artboard) has it
|
|
103
|
+
*/
|
|
104
|
+
function hasAnyTargeted(type) {
|
|
105
|
+
for (const target in targets) if (target !== '' && listensTo(target, type)) return true
|
|
106
|
+
return false
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** @returns {string[]} the targets that have a pointer interaction */
|
|
110
|
+
function names() {
|
|
111
|
+
const list = []
|
|
112
|
+
for (const target in targets) list.push(target)
|
|
113
|
+
return list
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The pointer is at a canvas pixel: targets it entered or left fire, and
|
|
118
|
+
* every one it is on fires a move.
|
|
119
|
+
*
|
|
120
|
+
* @param {number} x
|
|
121
|
+
* @param {number} y
|
|
122
|
+
*/
|
|
123
|
+
function moved(x, y) {
|
|
124
|
+
const list = names()
|
|
125
|
+
for (let n = 0; n < list.length; n++) {
|
|
126
|
+
const target = list[n]
|
|
127
|
+
const isNow = isOn(target, x, y)
|
|
128
|
+
if (isNow && !inside[target]) {
|
|
129
|
+
inside[target] = true
|
|
130
|
+
if (listensTo(target, 'PointerEnter')) options.fire('PointerEnter', target)
|
|
131
|
+
} else if (!isNow && inside[target]) {
|
|
132
|
+
inside[target] = false
|
|
133
|
+
pressed[target] = false
|
|
134
|
+
if (listensTo(target, 'PointerExit')) options.fire('PointerExit', target)
|
|
135
|
+
}
|
|
136
|
+
if (isNow && listensTo(target, 'PointerMove')) options.fire('PointerMove', target)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {number} x
|
|
142
|
+
* @param {number} y
|
|
143
|
+
*/
|
|
144
|
+
function pressedAt(x, y) {
|
|
145
|
+
moved(x, y)
|
|
146
|
+
const list = names()
|
|
147
|
+
for (let n = 0; n < list.length; n++) {
|
|
148
|
+
const target = list[n]
|
|
149
|
+
if (!isOn(target, x, y)) continue
|
|
150
|
+
pressed[target] = true
|
|
151
|
+
if (listensTo(target, 'PointerDown')) options.fire('PointerDown', target)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {number} x
|
|
157
|
+
* @param {number} y
|
|
158
|
+
*/
|
|
159
|
+
function releasedAt(x, y) {
|
|
160
|
+
const list = names()
|
|
161
|
+
for (let n = 0; n < list.length; n++) {
|
|
162
|
+
const target = list[n]
|
|
163
|
+
const wasPressed = pressed[target]
|
|
164
|
+
pressed[target] = false
|
|
165
|
+
if (!isOn(target, x, y)) continue
|
|
166
|
+
if (listensTo(target, 'PointerUp')) options.fire('PointerUp', target)
|
|
167
|
+
// a click on the whole canvas is the canvas's own `click` event
|
|
168
|
+
if (wasPressed && target !== '' && options.clicks && listensTo(target, 'Click')) options.fire('Click', target)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** The pointer left the canvas, or its touch ended: every target it was on is exited. */
|
|
173
|
+
function left() {
|
|
174
|
+
const list = names()
|
|
175
|
+
for (let n = 0; n < list.length; n++) {
|
|
176
|
+
const target = list[n]
|
|
177
|
+
pressed[target] = false
|
|
178
|
+
if (!inside[target]) continue
|
|
179
|
+
inside[target] = false
|
|
180
|
+
if (listensTo(target, 'PointerExit')) options.fire('PointerExit', target)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* A client position as canvas pixels, which the hit geometry is in.
|
|
186
|
+
*
|
|
187
|
+
* @param {{ clientX: number, clientY: number }} point
|
|
188
|
+
* @returns {{ x: number, y: number } | null} null while the canvas has no size
|
|
189
|
+
*/
|
|
190
|
+
function place(point) {
|
|
191
|
+
const box = canvas.getBoundingClientRect()
|
|
192
|
+
if (!box.width || !box.height) return null
|
|
193
|
+
return { x: ((point.clientX - box.left) * canvas.width) / box.width, y: ((point.clientY - box.top) * canvas.height) / box.height }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @param {(x: number, y: number) => void} then
|
|
198
|
+
* @param {{ clientX: number, clientY: number } | undefined} point
|
|
199
|
+
*/
|
|
200
|
+
function at(then, point) {
|
|
201
|
+
const where = point ? place(point) : null
|
|
202
|
+
if (where) then(where.x, where.y)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** @param {any} event */
|
|
206
|
+
const isMouseAfterTouch = (event) => event.type.indexOf('mouse') === 0 && Date.now() - lastTouch < TOUCH_MOUSE_MS
|
|
207
|
+
|
|
208
|
+
/** @param {any} event */
|
|
209
|
+
const firstTouch = (event) => (event.changedTouches && event.changedTouches[0]) || (event.touches && event.touches[0])
|
|
210
|
+
|
|
211
|
+
/** @type {Record<string, (event: any) => void>} */
|
|
212
|
+
const handlers = {
|
|
213
|
+
// pen, touch and mouse together
|
|
214
|
+
pointerdown: (event) => {
|
|
215
|
+
if (event.button) return
|
|
216
|
+
at(pressedAt, event)
|
|
217
|
+
},
|
|
218
|
+
pointermove: (event) => at(moved, event),
|
|
219
|
+
pointerup: (event) => {
|
|
220
|
+
if (event.button) return
|
|
221
|
+
at(releasedAt, event)
|
|
222
|
+
// a finger has no hover: lifting it leaves
|
|
223
|
+
if (event.pointerType && event.pointerType !== 'mouse') left()
|
|
224
|
+
},
|
|
225
|
+
pointercancel: () => left(),
|
|
226
|
+
pointerleave: () => left(),
|
|
227
|
+
|
|
228
|
+
// the browsers before pointer events
|
|
229
|
+
mousedown: (event) => {
|
|
230
|
+
if (isMouseAfterTouch(event) || event.button) return
|
|
231
|
+
at(pressedAt, event)
|
|
232
|
+
},
|
|
233
|
+
mousemove: (event) => {
|
|
234
|
+
if (!isMouseAfterTouch(event)) at(moved, event)
|
|
235
|
+
},
|
|
236
|
+
mouseup: (event) => {
|
|
237
|
+
if (isMouseAfterTouch(event) || event.button) return
|
|
238
|
+
at(releasedAt, event)
|
|
239
|
+
},
|
|
240
|
+
mouseleave: (event) => {
|
|
241
|
+
if (!isMouseAfterTouch(event)) left()
|
|
242
|
+
},
|
|
243
|
+
touchstart: (event) => {
|
|
244
|
+
lastTouch = Date.now()
|
|
245
|
+
at(pressedAt, firstTouch(event))
|
|
246
|
+
},
|
|
247
|
+
touchmove: (event) => {
|
|
248
|
+
lastTouch = Date.now()
|
|
249
|
+
at(moved, firstTouch(event))
|
|
250
|
+
},
|
|
251
|
+
touchend: (event) => {
|
|
252
|
+
lastTouch = Date.now()
|
|
253
|
+
at(releasedAt, firstTouch(event))
|
|
254
|
+
left()
|
|
255
|
+
},
|
|
256
|
+
touchcancel: () => {
|
|
257
|
+
lastTouch = Date.now()
|
|
258
|
+
left()
|
|
259
|
+
},
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function bind() {
|
|
263
|
+
const events = window.PointerEvent
|
|
264
|
+
? [ 'pointerdown', 'pointermove', 'pointerup', 'pointercancel', 'pointerleave' ]
|
|
265
|
+
: [ 'mousedown', 'mousemove', 'mouseup', 'mouseleave', 'touchstart', 'touchmove', 'touchend', 'touchcancel' ]
|
|
266
|
+
for (let n = 0; n < events.length; n++) {
|
|
267
|
+
bound.push({ name: events[n], listener: handlers[events[n]] })
|
|
268
|
+
canvas.addEventListener(events[n], handlers[events[n]], false)
|
|
269
|
+
}
|
|
270
|
+
isBound = true
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function unbind() {
|
|
274
|
+
for (let n = 0; n < bound.length; n++) canvas.removeEventListener(bound[n].name, bound[n].listener, false)
|
|
275
|
+
bound.length = 0
|
|
276
|
+
isBound = false
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
listen,
|
|
281
|
+
destroy() {
|
|
282
|
+
unbind()
|
|
283
|
+
targets = {}
|
|
284
|
+
},
|
|
285
|
+
/** The targets the pointer is on now, for tests and hosts */
|
|
286
|
+
get hovering() {
|
|
287
|
+
const list = []
|
|
288
|
+
for (const target in inside) if (inside[target] && target !== '') list.push(target)
|
|
289
|
+
return list
|
|
290
|
+
},
|
|
291
|
+
}
|
|
292
|
+
}
|