@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,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `math` library, and `os`. Functions ES5 lacks (`sinh`, `log10`, `sign`,
|
|
3
|
+
* ...) are written out, because the oldest browsers this runs in lack them.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { LuaTable } from '../../vm/vm.value.js'
|
|
7
|
+
import { sign, trunc } from '../../vm/vm.num.js'
|
|
8
|
+
import { argError, checkInt, checkNumber, optNumber, register } from '../lib.args.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {number} x
|
|
12
|
+
* @returns {number}
|
|
13
|
+
*/
|
|
14
|
+
function sinh(x) {
|
|
15
|
+
return (Math.exp(x) - Math.exp(-x)) / 2
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {number} x
|
|
20
|
+
* @returns {number}
|
|
21
|
+
*/
|
|
22
|
+
function cosh(x) {
|
|
23
|
+
return (Math.exp(x) + Math.exp(-x)) / 2
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {number} x
|
|
28
|
+
* @returns {number}
|
|
29
|
+
*/
|
|
30
|
+
function tanh(x) {
|
|
31
|
+
if (x > 20) return 1
|
|
32
|
+
if (x < -20) return -1
|
|
33
|
+
const a = Math.exp(2 * x)
|
|
34
|
+
return (a - 1) / (a + 1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The log of x in base `b`, exact where x is a power of b.
|
|
39
|
+
*
|
|
40
|
+
* @param {number} x
|
|
41
|
+
* @param {number} lnb the natural log of the base
|
|
42
|
+
* @param {number} b
|
|
43
|
+
* @returns {number}
|
|
44
|
+
*/
|
|
45
|
+
function logBase(x, lnb, b) {
|
|
46
|
+
const r = Math.log(x) / lnb
|
|
47
|
+
const rounded = Math.round(r)
|
|
48
|
+
return Math.abs(r - rounded) < 1e-9 && Math.pow(b, rounded) === x ? rounded : r
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A small deterministic generator (mulberry32), 32 bits of state.
|
|
53
|
+
*
|
|
54
|
+
* @param {number} seed
|
|
55
|
+
*/
|
|
56
|
+
function makeRandom(seed) {
|
|
57
|
+
let state = seed >>> 0
|
|
58
|
+
return function () {
|
|
59
|
+
state = (state + 0x6d2b79f5) >>> 0
|
|
60
|
+
let t = state
|
|
61
|
+
t = Math.imul(t ^ (t >>> 15), t | 1)
|
|
62
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
|
|
63
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
69
|
+
* @param {LuaTable} G
|
|
70
|
+
*/
|
|
71
|
+
export function installMath(vm, G) {
|
|
72
|
+
const math = new LuaTable()
|
|
73
|
+
G.set('math', math)
|
|
74
|
+
let random = makeRandom(0x2545f491)
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* One-argument functions.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} name
|
|
80
|
+
* @param {(x: number) => number} f
|
|
81
|
+
*/
|
|
82
|
+
const unary = function (name, f) {
|
|
83
|
+
math.set(name, vm.native('math.' + name, function (vm2, args) {
|
|
84
|
+
return f(checkNumber(args, 0, name))
|
|
85
|
+
}))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
unary('abs', Math.abs)
|
|
89
|
+
unary('acos', Math.acos)
|
|
90
|
+
unary('asin', Math.asin)
|
|
91
|
+
unary('atan', Math.atan)
|
|
92
|
+
unary('ceil', Math.ceil)
|
|
93
|
+
unary('cos', Math.cos)
|
|
94
|
+
unary('cosh', cosh)
|
|
95
|
+
unary('deg', function (x) { return x * (180 / Math.PI) })
|
|
96
|
+
unary('exp', Math.exp)
|
|
97
|
+
unary('floor', Math.floor)
|
|
98
|
+
unary('log10', function (x) { return logBase(x, Math.LN10, 10) })
|
|
99
|
+
unary('rad', function (x) { return x * (Math.PI / 180) })
|
|
100
|
+
unary('sin', Math.sin)
|
|
101
|
+
unary('sinh', sinh)
|
|
102
|
+
unary('sqrt', Math.sqrt)
|
|
103
|
+
unary('tan', Math.tan)
|
|
104
|
+
unary('tanh', tanh)
|
|
105
|
+
unary('sign', sign)
|
|
106
|
+
unary('round', function (x) { return x < 0 ? -Math.floor(-x + 0.5) : Math.floor(x + 0.5) })
|
|
107
|
+
unary('isnan', function (x) { return /** @type {any} */ (x !== x) })
|
|
108
|
+
unary('isinf', function (x) { return /** @type {any} */ (x === Infinity || x === -Infinity) })
|
|
109
|
+
unary('isfinite', function (x) { return /** @type {any} */ (x === x && x !== Infinity && x !== -Infinity) })
|
|
110
|
+
|
|
111
|
+
register(math, {
|
|
112
|
+
atan2(vm, args) {
|
|
113
|
+
return Math.atan2(checkNumber(args, 0, 'atan2'), checkNumber(args, 1, 'atan2'))
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
fmod(vm, args) {
|
|
117
|
+
return checkNumber(args, 0, 'fmod') % checkNumber(args, 1, 'fmod')
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
frexp(vm, args) {
|
|
121
|
+
const x = checkNumber(args, 0, 'frexp')
|
|
122
|
+
if (x === 0 || x !== x || x === Infinity || x === -Infinity) return [ x, 0 ]
|
|
123
|
+
let e = Math.max(-1023, Math.floor(logBase(Math.abs(x), Math.LN2, 2)) + 1)
|
|
124
|
+
let m = x * Math.pow(2, -e)
|
|
125
|
+
while (Math.abs(m) < 0.5) {
|
|
126
|
+
m *= 2
|
|
127
|
+
e--
|
|
128
|
+
}
|
|
129
|
+
while (Math.abs(m) >= 1) {
|
|
130
|
+
m /= 2
|
|
131
|
+
e++
|
|
132
|
+
}
|
|
133
|
+
return [ m, e ]
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
ldexp(vm, args) {
|
|
137
|
+
return checkNumber(args, 0, 'ldexp') * Math.pow(2, checkInt(args, 1, 'ldexp'))
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
log(vm, args) {
|
|
141
|
+
const x = checkNumber(args, 0, 'log')
|
|
142
|
+
if (args[1] === undefined) return Math.log(x)
|
|
143
|
+
const b = checkNumber(args, 1, 'log')
|
|
144
|
+
if (b === 2) return logBase(x, Math.LN2, 2)
|
|
145
|
+
if (b === 10) return logBase(x, Math.LN10, 10)
|
|
146
|
+
return Math.log(x) / Math.log(b)
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
max(vm, args) {
|
|
150
|
+
let m = checkNumber(args, 0, 'max')
|
|
151
|
+
for (let i = 1; i < args.length; i++) {
|
|
152
|
+
const v = checkNumber(args, i, 'max')
|
|
153
|
+
if (v > m) m = v
|
|
154
|
+
}
|
|
155
|
+
return m
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
min(vm, args) {
|
|
159
|
+
let m = checkNumber(args, 0, 'min')
|
|
160
|
+
for (let i = 1; i < args.length; i++) {
|
|
161
|
+
const v = checkNumber(args, i, 'min')
|
|
162
|
+
if (v < m) m = v
|
|
163
|
+
}
|
|
164
|
+
return m
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
modf(vm, args) {
|
|
168
|
+
const x = checkNumber(args, 0, 'modf')
|
|
169
|
+
const whole = trunc(x)
|
|
170
|
+
return [ whole, x - whole ]
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
pow(vm, args) {
|
|
174
|
+
return Math.pow(checkNumber(args, 0, 'pow'), checkNumber(args, 1, 'pow'))
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
clamp(vm, args) {
|
|
178
|
+
const v = checkNumber(args, 0, 'clamp')
|
|
179
|
+
const lo = checkNumber(args, 1, 'clamp')
|
|
180
|
+
const hi = checkNumber(args, 2, 'clamp')
|
|
181
|
+
if (lo > hi) throw argError(3, 'clamp', 'max must be greater than min')
|
|
182
|
+
return v < lo ? lo : v > hi ? hi : v
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
lerp(vm, args) {
|
|
186
|
+
const a = checkNumber(args, 0, 'lerp')
|
|
187
|
+
const b = checkNumber(args, 1, 'lerp')
|
|
188
|
+
const t = checkNumber(args, 2, 'lerp')
|
|
189
|
+
return t === 1 ? b : a + (b - a) * t
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
random(vm, args) {
|
|
193
|
+
const r = random()
|
|
194
|
+
if (args.length === 0) return r
|
|
195
|
+
const lo = args.length === 1 ? 1 : checkInt(args, 0, 'random')
|
|
196
|
+
const hi = checkInt(args, args.length === 1 ? 0 : 1, 'random')
|
|
197
|
+
if (lo > hi) throw argError(args.length === 1 ? 1 : 2, 'random', 'interval is empty')
|
|
198
|
+
return lo + Math.floor(r * (hi - lo + 1))
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
randomseed(vm, args) {
|
|
202
|
+
random = makeRandom(checkInt(args, 0, 'randomseed'))
|
|
203
|
+
return []
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
noise(vm, args) {
|
|
207
|
+
return noise(checkNumber(args, 0, 'noise'), optNumber(args, 1, 'noise', 0), optNumber(args, 2, 'noise', 0))
|
|
208
|
+
},
|
|
209
|
+
}, 'math.')
|
|
210
|
+
|
|
211
|
+
math.set('pi', Math.PI)
|
|
212
|
+
math.set('huge', Infinity)
|
|
213
|
+
|
|
214
|
+
// os
|
|
215
|
+
const os = new LuaTable()
|
|
216
|
+
G.set('os', os)
|
|
217
|
+
register(os, {
|
|
218
|
+
clock() {
|
|
219
|
+
return now() / 1000
|
|
220
|
+
},
|
|
221
|
+
time() {
|
|
222
|
+
return Math.floor(Date.now() / 1000)
|
|
223
|
+
},
|
|
224
|
+
}, 'os.')
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** @returns {number} milliseconds, from a clock that only moves forward where the host has one */
|
|
228
|
+
function now() {
|
|
229
|
+
const perf = typeof performance !== 'undefined' ? performance : null
|
|
230
|
+
return perf !== null && typeof perf.now === 'function' ? perf.now() : Date.now()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Perlin gradient noise in 1 to 3 dimensions, in about -1..1.
|
|
235
|
+
*
|
|
236
|
+
* @param {number} x
|
|
237
|
+
* @param {number} y
|
|
238
|
+
* @param {number} z
|
|
239
|
+
* @returns {number}
|
|
240
|
+
*/
|
|
241
|
+
function noise(x, y, z) {
|
|
242
|
+
const xi = Math.floor(x)
|
|
243
|
+
const yi = Math.floor(y)
|
|
244
|
+
const zi = Math.floor(z)
|
|
245
|
+
const xf = x - xi
|
|
246
|
+
const yf = y - yi
|
|
247
|
+
const zf = z - zi
|
|
248
|
+
/** @param {number} t */
|
|
249
|
+
const fade = function (t) { return t * t * t * (t * (t * 6 - 15) + 10) }
|
|
250
|
+
/**
|
|
251
|
+
* @param {number} a
|
|
252
|
+
* @param {number} b
|
|
253
|
+
* @param {number} c
|
|
254
|
+
*/
|
|
255
|
+
const hash = function (a, b, c) {
|
|
256
|
+
let h = Math.imul(a, 374761393) + Math.imul(b, 668265263) + Math.imul(c, 1274126177)
|
|
257
|
+
h = Math.imul(h ^ (h >>> 13), 1274126177)
|
|
258
|
+
return (h ^ (h >>> 16)) & 15
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* @param {number} h
|
|
262
|
+
* @param {number} dx
|
|
263
|
+
* @param {number} dy
|
|
264
|
+
* @param {number} dz
|
|
265
|
+
*/
|
|
266
|
+
const grad = function (h, dx, dy, dz) {
|
|
267
|
+
const u = h < 8 ? dx : dy
|
|
268
|
+
const v = h < 4 ? dy : h === 12 || h === 14 ? dx : dz
|
|
269
|
+
return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v)
|
|
270
|
+
}
|
|
271
|
+
const u = fade(xf)
|
|
272
|
+
const v = fade(yf)
|
|
273
|
+
const w = fade(zf)
|
|
274
|
+
/**
|
|
275
|
+
* @param {number} a
|
|
276
|
+
* @param {number} b
|
|
277
|
+
* @param {number} t
|
|
278
|
+
*/
|
|
279
|
+
const lerp = function (a, b, t) { return a + (b - a) * t }
|
|
280
|
+
const c = function (/** @type {number} */ dx, /** @type {number} */ dy, /** @type {number} */ dz) {
|
|
281
|
+
return grad(hash(xi + dx, yi + dy, zi + dz), xf - dx, yf - dy, zf - dz)
|
|
282
|
+
}
|
|
283
|
+
return lerp(
|
|
284
|
+
lerp(lerp(c(0, 0, 0), c(1, 0, 0), u), lerp(c(0, 1, 0), c(1, 1, 0), u), v),
|
|
285
|
+
lerp(lerp(c(0, 0, 1), c(1, 0, 1), u), lerp(c(0, 1, 1), c(1, 1, 1), u), v),
|
|
286
|
+
w,
|
|
287
|
+
)
|
|
288
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `vector` library: the three-component vector value's functions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { LuaTable, Vector, fround } from '../../vm/vm.value.js'
|
|
6
|
+
import { sign } from '../../vm/vm.num.js'
|
|
7
|
+
import { checkNumber, register, typeError } from '../lib.args.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {any[]} args
|
|
11
|
+
* @param {number} i
|
|
12
|
+
* @param {string} name
|
|
13
|
+
* @returns {Vector}
|
|
14
|
+
*/
|
|
15
|
+
function checkVector(args, i, name) {
|
|
16
|
+
const v = args[i]
|
|
17
|
+
if (!(v instanceof Vector)) throw typeError(args, i, name, 'vector')
|
|
18
|
+
return v
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {Vector} v
|
|
23
|
+
* @returns {number}
|
|
24
|
+
*/
|
|
25
|
+
function magnitude(v) {
|
|
26
|
+
return fround(Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
31
|
+
* @param {LuaTable} G
|
|
32
|
+
*/
|
|
33
|
+
export function installVector(vm, G) {
|
|
34
|
+
const lib = new LuaTable()
|
|
35
|
+
G.set('vector', lib)
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A function of one vector that maps each component.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} name
|
|
41
|
+
* @param {(n: number) => number} f
|
|
42
|
+
*/
|
|
43
|
+
const mapped = function (name, f) {
|
|
44
|
+
lib.set(name, vm.native('vector.' + name, function (vm2, args) {
|
|
45
|
+
const v = checkVector(args, 0, name)
|
|
46
|
+
return new Vector(f(v.x), f(v.y), f(v.z))
|
|
47
|
+
}))
|
|
48
|
+
}
|
|
49
|
+
mapped('floor', Math.floor)
|
|
50
|
+
mapped('ceil', Math.ceil)
|
|
51
|
+
mapped('abs', Math.abs)
|
|
52
|
+
mapped('sign', sign)
|
|
53
|
+
|
|
54
|
+
register(lib, {
|
|
55
|
+
create(vm, args) {
|
|
56
|
+
return new Vector(checkNumber(args, 0, 'create'), checkNumber(args, 1, 'create'), args[2] === undefined ? 0 : checkNumber(args, 2, 'create'))
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
magnitude(vm, args) {
|
|
60
|
+
return magnitude(checkVector(args, 0, 'magnitude'))
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
normalize(vm, args) {
|
|
64
|
+
const v = checkVector(args, 0, 'normalize')
|
|
65
|
+
const m = magnitude(v)
|
|
66
|
+
return new Vector(v.x / m, v.y / m, v.z / m)
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
dot(vm, args) {
|
|
70
|
+
const a = checkVector(args, 0, 'dot')
|
|
71
|
+
const b = checkVector(args, 1, 'dot')
|
|
72
|
+
return fround(a.x * b.x + a.y * b.y + a.z * b.z)
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
cross(vm, args) {
|
|
76
|
+
const a = checkVector(args, 0, 'cross')
|
|
77
|
+
const b = checkVector(args, 1, 'cross')
|
|
78
|
+
return new Vector(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x)
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
angle(vm, args) {
|
|
82
|
+
const a = checkVector(args, 0, 'angle')
|
|
83
|
+
const b = checkVector(args, 1, 'angle')
|
|
84
|
+
const cx = a.y * b.z - a.z * b.y
|
|
85
|
+
const cy = a.z * b.x - a.x * b.z
|
|
86
|
+
const cz = a.x * b.y - a.y * b.x
|
|
87
|
+
return Math.atan2(Math.sqrt(cx * cx + cy * cy + cz * cz), a.x * b.x + a.y * b.y + a.z * b.z)
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
clamp(vm, args) {
|
|
91
|
+
const v = checkVector(args, 0, 'clamp')
|
|
92
|
+
const lo = checkVector(args, 1, 'clamp')
|
|
93
|
+
const hi = checkVector(args, 2, 'clamp')
|
|
94
|
+
return new Vector(Math.min(Math.max(v.x, lo.x), hi.x), Math.min(Math.max(v.y, lo.y), hi.y), Math.min(Math.max(v.z, lo.z), hi.z))
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
min(vm, args) {
|
|
98
|
+
let r = checkVector(args, 0, 'min')
|
|
99
|
+
for (let i = 1; i < args.length; i++) {
|
|
100
|
+
const v = checkVector(args, i, 'min')
|
|
101
|
+
r = new Vector(Math.min(r.x, v.x), Math.min(r.y, v.y), Math.min(r.z, v.z))
|
|
102
|
+
}
|
|
103
|
+
return r
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
max(vm, args) {
|
|
107
|
+
let r = checkVector(args, 0, 'max')
|
|
108
|
+
for (let i = 1; i < args.length; i++) {
|
|
109
|
+
const v = checkVector(args, i, 'max')
|
|
110
|
+
r = new Vector(Math.max(r.x, v.x), Math.max(r.y, v.y), Math.max(r.z, v.z))
|
|
111
|
+
}
|
|
112
|
+
return r
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
lerp(vm, args) {
|
|
116
|
+
const a = checkVector(args, 0, 'lerp')
|
|
117
|
+
const b = checkVector(args, 1, 'lerp')
|
|
118
|
+
const t = checkNumber(args, 2, 'lerp')
|
|
119
|
+
return new Vector(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t)
|
|
120
|
+
},
|
|
121
|
+
}, 'vector.')
|
|
122
|
+
|
|
123
|
+
lib.set('zero', new Vector(0, 0, 0))
|
|
124
|
+
lib.set('one', new Vector(1, 1, 1))
|
|
125
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `string.format`: C's printf conversions as Lua uses them.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { fail } from '../../vm/vm.value.js'
|
|
6
|
+
import { formatE, formatF, formatG, repeat, trunc } from '../../vm/vm.num.js'
|
|
7
|
+
import { checkNumber, checkString } from '../lib.args.js'
|
|
8
|
+
|
|
9
|
+
const SPEC = /^%([-+ #0]*)(\d*)(?:\.(\d*))?([a-zA-Z%])/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Pads `body` (with its sign or prefix split off) to `width`.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} sign '-', '+', ' ', a `0x` prefix or ''
|
|
15
|
+
* @param {string} body
|
|
16
|
+
* @param {number} width
|
|
17
|
+
* @param {string} flags
|
|
18
|
+
* @param {boolean} zeroOk whether the 0 flag pads with zeros here
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
function pad(sign, body, width, flags, zeroOk) {
|
|
22
|
+
const n = width - sign.length - body.length
|
|
23
|
+
if (n <= 0) return sign + body
|
|
24
|
+
if (flags.indexOf('-') >= 0) return sign + body + repeat(' ', n)
|
|
25
|
+
if (flags.indexOf('0') >= 0 && zeroOk) return sign + repeat('0', n) + body
|
|
26
|
+
return repeat(' ', n) + sign + body
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} s
|
|
31
|
+
* @returns {string} s as a Lua string literal that reads back as s (`%q`)
|
|
32
|
+
*/
|
|
33
|
+
function quote(s) {
|
|
34
|
+
let out = '"'
|
|
35
|
+
for (let i = 0; i < s.length; i++) {
|
|
36
|
+
const c = s.charCodeAt(i)
|
|
37
|
+
const ch = s.charAt(i)
|
|
38
|
+
if (ch === '"' || ch === '\\') out += '\\' + ch
|
|
39
|
+
else if (c === 10) out += '\\\n'
|
|
40
|
+
else if (c === 13) out += '\\r'
|
|
41
|
+
else if (c === 0) out += '\\000'
|
|
42
|
+
else out += ch
|
|
43
|
+
}
|
|
44
|
+
return out + '"'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
49
|
+
* @param {any[]} args the format string, then the values
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
52
|
+
export function format(vm, args) {
|
|
53
|
+
const fmt = checkString(args, 0, 'format')
|
|
54
|
+
let out = ''
|
|
55
|
+
let arg = 0
|
|
56
|
+
let i = 0
|
|
57
|
+
while (i < fmt.length) {
|
|
58
|
+
const pct = fmt.indexOf('%', i)
|
|
59
|
+
if (pct < 0) {
|
|
60
|
+
out += fmt.substring(i)
|
|
61
|
+
break
|
|
62
|
+
}
|
|
63
|
+
out += fmt.substring(i, pct)
|
|
64
|
+
const m = SPEC.exec(fmt.substring(pct))
|
|
65
|
+
if (m === null) throw fail("invalid option '%" + fmt.charAt(pct + 1) + "' to 'format'")
|
|
66
|
+
i = pct + m[0].length
|
|
67
|
+
const flags = m[1]
|
|
68
|
+
const width = m[2] === '' ? 0 : parseInt(m[2], 10)
|
|
69
|
+
const hasPrecision = m[3] !== undefined
|
|
70
|
+
const precision = hasPrecision ? (m[3] === '' ? 0 : parseInt(m[3], 10)) : -1
|
|
71
|
+
const conv = m[4]
|
|
72
|
+
if (conv === '%') {
|
|
73
|
+
out += '%'
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
arg++
|
|
77
|
+
if (arg >= args.length) throw fail('missing argument #' + (arg + 1))
|
|
78
|
+
const signOf = function (/** @type {boolean} */ negative) {
|
|
79
|
+
return negative ? '-' : flags.indexOf('+') >= 0 ? '+' : flags.indexOf(' ') >= 0 ? ' ' : ''
|
|
80
|
+
}
|
|
81
|
+
switch (conv) {
|
|
82
|
+
case 'd':
|
|
83
|
+
case 'i':
|
|
84
|
+
case 'u': {
|
|
85
|
+
const n = trunc(checkNumber(args, arg, 'format'))
|
|
86
|
+
let body = String(Math.abs(n))
|
|
87
|
+
if (hasPrecision) while (body.length < precision) body = '0' + body
|
|
88
|
+
out += pad(signOf(n < 0), body, width, flags, !hasPrecision)
|
|
89
|
+
break
|
|
90
|
+
}
|
|
91
|
+
case 'c':
|
|
92
|
+
out += pad('', String.fromCharCode(trunc(checkNumber(args, arg, 'format')) & 255), width, flags, false)
|
|
93
|
+
break
|
|
94
|
+
case 'x':
|
|
95
|
+
case 'X':
|
|
96
|
+
case 'o': {
|
|
97
|
+
let n = trunc(checkNumber(args, arg, 'format'))
|
|
98
|
+
if (n < 0) n += 4294967296
|
|
99
|
+
let body = n.toString(conv === 'o' ? 8 : 16)
|
|
100
|
+
if (conv === 'X') body = body.toUpperCase()
|
|
101
|
+
if (hasPrecision) while (body.length < precision) body = '0' + body
|
|
102
|
+
const prefix = flags.indexOf('#') >= 0 && n !== 0 ? (conv === 'o' ? '0' : conv === 'x' ? '0x' : '0X') : ''
|
|
103
|
+
out += pad(prefix, body, width, flags, !hasPrecision)
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
case 'e':
|
|
107
|
+
case 'E':
|
|
108
|
+
case 'f':
|
|
109
|
+
case 'F':
|
|
110
|
+
case 'g':
|
|
111
|
+
case 'G': {
|
|
112
|
+
const n = checkNumber(args, arg, 'format')
|
|
113
|
+
const upper = conv === 'E' || conv === 'G' || conv === 'F'
|
|
114
|
+
const alt = flags.indexOf('#') >= 0
|
|
115
|
+
const finite = n === n && n !== Infinity && n !== -Infinity
|
|
116
|
+
const neg = n < 0 || (n === 0 && 1 / n < 0)
|
|
117
|
+
let body
|
|
118
|
+
if (!finite) body = n !== n ? 'nan' : 'inf'
|
|
119
|
+
else {
|
|
120
|
+
const p = hasPrecision ? precision : 6
|
|
121
|
+
const a = Math.abs(n)
|
|
122
|
+
const lower = conv.toLowerCase()
|
|
123
|
+
body = lower === 'e' ? formatE(a, p, alt) : lower === 'f' ? formatF(a, p, alt) : formatG(a, p, alt)
|
|
124
|
+
}
|
|
125
|
+
if (upper) body = body.toUpperCase()
|
|
126
|
+
out += pad(signOf(neg), body, width, flags, finite)
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
case 'q':
|
|
130
|
+
out += quote(checkString(args, arg, 'format'))
|
|
131
|
+
break
|
|
132
|
+
case 's': {
|
|
133
|
+
let s = checkString(args, arg, 'format')
|
|
134
|
+
if (hasPrecision) s = s.substring(0, precision)
|
|
135
|
+
out += pad('', s, width, flags, false)
|
|
136
|
+
break
|
|
137
|
+
}
|
|
138
|
+
default:
|
|
139
|
+
throw fail("invalid option '%" + conv + "' to 'format'")
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return out
|
|
143
|
+
}
|