@px-petals/roku.motion-web 1.0.0 → 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/bands/bands.js +3 -1
- package/bundle/bundle.js +56 -0
- package/list/list.js +12 -1
- package/lottie/lottie.layers.js +64 -11
- package/lottie/lottie.paint.js +30 -0
- package/lottie/lottie.paths.js +19 -4
- package/lottie/lottie.props.js +18 -8
- package/lottie/lottie.shapes.js +2 -1
- package/mixer/mixer.js +31 -8
- package/mixer/mixer.mix.js +17 -0
- package/motion/motion.convert.js +32 -1
- package/motion/motion.flow.js +20 -2
- package/motion/motion.machine.js +28 -13
- package/motion/motion.values.js +13 -9
- package/motion.js +196 -20
- package/package.json +10 -16
- package/player/player.js +25 -5
- package/readme.md +78 -3
- 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
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argument checks for native library functions, with Luau's messages
|
|
3
|
+
* (`invalid argument #1 to 'insert' (table expected, got nil)`).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { LuaTable, NativeFunction, LuaClosure, fail, typeName } from '../vm/vm.value.js'
|
|
7
|
+
import { toNumber } from '../vm/vm.meta.js'
|
|
8
|
+
import { numberToString } from '../vm/vm.num.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {number} n 1-based argument number
|
|
12
|
+
* @param {string} fname
|
|
13
|
+
* @param {string} message
|
|
14
|
+
*/
|
|
15
|
+
export function argError(n, fname, message) {
|
|
16
|
+
return fail('invalid argument #' + n + " to '" + fname + "' (" + message + ')')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {any[]} args
|
|
21
|
+
* @param {number} i 0-based
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
function got(args, i) {
|
|
25
|
+
return typeName(args[i])
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The error for an argument of the wrong type: Luau says "missing argument"
|
|
30
|
+
* when there is none at all, and "invalid argument" with the type it got otherwise.
|
|
31
|
+
*
|
|
32
|
+
* @param {any[]} args
|
|
33
|
+
* @param {number} i 0-based
|
|
34
|
+
* @param {string} fname
|
|
35
|
+
* @param {string} expected such as 'table'
|
|
36
|
+
*/
|
|
37
|
+
export function typeError(args, i, fname, expected) {
|
|
38
|
+
if (i >= args.length) return fail('missing argument #' + (i + 1) + " to '" + fname + "' (" + expected + ' expected)')
|
|
39
|
+
return argError(i + 1, fname, expected + ' expected, got ' + got(args, i))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {any[]} args
|
|
44
|
+
* @param {number} i 0-based
|
|
45
|
+
* @param {string} fname
|
|
46
|
+
* @returns {LuaTable}
|
|
47
|
+
*/
|
|
48
|
+
export function checkTable(args, i, fname) {
|
|
49
|
+
const v = args[i]
|
|
50
|
+
if (!(v instanceof LuaTable)) throw typeError(args, i, fname, 'table')
|
|
51
|
+
return v
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {any[]} args
|
|
56
|
+
* @param {number} i
|
|
57
|
+
* @param {string} fname
|
|
58
|
+
* @returns {number} a number, or a string that reads as one
|
|
59
|
+
*/
|
|
60
|
+
export function checkNumber(args, i, fname) {
|
|
61
|
+
const n = toNumber(args[i])
|
|
62
|
+
if (n === undefined) throw typeError(args, i, fname, 'number')
|
|
63
|
+
return n
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {any[]} args
|
|
68
|
+
* @param {number} i
|
|
69
|
+
* @param {string} fname
|
|
70
|
+
* @param {number} def
|
|
71
|
+
* @returns {number}
|
|
72
|
+
*/
|
|
73
|
+
export function optNumber(args, i, fname, def) {
|
|
74
|
+
return args[i] === undefined ? def : checkNumber(args, i, fname)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @param {any[]} args
|
|
79
|
+
* @param {number} i
|
|
80
|
+
* @param {string} fname
|
|
81
|
+
* @returns {number} an integer: the number cut toward zero
|
|
82
|
+
*/
|
|
83
|
+
export function checkInt(args, i, fname) {
|
|
84
|
+
const n = checkNumber(args, i, fname)
|
|
85
|
+
return n < 0 ? Math.ceil(n) : Math.floor(n)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @param {any[]} args
|
|
90
|
+
* @param {number} i
|
|
91
|
+
* @param {string} fname
|
|
92
|
+
* @param {number} def
|
|
93
|
+
* @returns {number}
|
|
94
|
+
*/
|
|
95
|
+
export function optInt(args, i, fname, def) {
|
|
96
|
+
return args[i] === undefined ? def : checkInt(args, i, fname)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {any[]} args
|
|
101
|
+
* @param {number} i
|
|
102
|
+
* @param {string} fname
|
|
103
|
+
* @returns {string} a string, or a number written as one
|
|
104
|
+
*/
|
|
105
|
+
export function checkString(args, i, fname) {
|
|
106
|
+
const v = args[i]
|
|
107
|
+
if (typeof v === 'string') return v
|
|
108
|
+
if (typeof v === 'number') return numberToString(v)
|
|
109
|
+
throw typeError(args, i, fname, 'string')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {any[]} args
|
|
114
|
+
* @param {number} i
|
|
115
|
+
* @param {string} fname
|
|
116
|
+
* @param {string} def
|
|
117
|
+
* @returns {string}
|
|
118
|
+
*/
|
|
119
|
+
export function optString(args, i, fname, def) {
|
|
120
|
+
return args[i] === undefined ? def : checkString(args, i, fname)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {any[]} args
|
|
125
|
+
* @param {number} i
|
|
126
|
+
* @param {string} fname
|
|
127
|
+
* @returns {any} a function
|
|
128
|
+
*/
|
|
129
|
+
export function checkFunction(args, i, fname) {
|
|
130
|
+
const v = args[i]
|
|
131
|
+
if (!(v instanceof LuaClosure) && !(v instanceof NativeFunction)) throw typeError(args, i, fname, 'function')
|
|
132
|
+
return v
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @param {any[]} args
|
|
137
|
+
* @param {number} i
|
|
138
|
+
*/
|
|
139
|
+
export function checkAny(args, i) {
|
|
140
|
+
if (i >= args.length) throw fail('missing argument #' + (i + 1))
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Puts native functions into a table under their names.
|
|
145
|
+
*
|
|
146
|
+
* @param {LuaTable} table
|
|
147
|
+
* @param {Record<string, import('../vm/vm.value.js').NativeCall>} fns
|
|
148
|
+
* @param {string} [prefix] such as 'string.', so errors and `tostring` name the function
|
|
149
|
+
*/
|
|
150
|
+
export function register(table, fns, prefix) {
|
|
151
|
+
for (const name in fns) table.set(name, new NativeFunction((prefix || '') + name, fns[name]))
|
|
152
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installs the standard library subset into a VM's globals: base, `string`,
|
|
3
|
+
* `table`, `math`, `bit32`, `vector` and `os`. The host adds its own globals
|
|
4
|
+
* to `vm.globals` afterwards.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { installBase } from './base/base.js'
|
|
8
|
+
import { installTable } from './base/base.table.js'
|
|
9
|
+
import { installBit32 } from './math/math.bit32.js'
|
|
10
|
+
import { installMath } from './math/math.js'
|
|
11
|
+
import { installVector } from './math/math.vector.js'
|
|
12
|
+
import { installString } from './string/string.js'
|
|
13
|
+
|
|
14
|
+
/** @param {import('../vm/vm.js').VM} vm */
|
|
15
|
+
export function installLibs(vm) {
|
|
16
|
+
const G = vm.globals
|
|
17
|
+
installBase(vm, G)
|
|
18
|
+
installString(vm, G)
|
|
19
|
+
installTable(vm, G)
|
|
20
|
+
installMath(vm, G)
|
|
21
|
+
installBit32(vm, G)
|
|
22
|
+
installVector(vm, G)
|
|
23
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `bit32` library: 32-bit unsigned integer operations on doubles.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { LuaTable, fail } from '../../vm/vm.value.js'
|
|
6
|
+
import { argError, checkNumber, register } from '../lib.args.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {any[]} args
|
|
10
|
+
* @param {number} i
|
|
11
|
+
* @param {string} name
|
|
12
|
+
* @returns {number} the argument as an unsigned 32-bit integer
|
|
13
|
+
*/
|
|
14
|
+
function u32(args, i, name) {
|
|
15
|
+
return checkNumber(args, i, name) >>> 0
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {number} x
|
|
20
|
+
* @param {number} disp positive shifts left, negative right
|
|
21
|
+
* @returns {number}
|
|
22
|
+
*/
|
|
23
|
+
function shift(x, disp) {
|
|
24
|
+
if (disp <= -32 || disp >= 32) return 0
|
|
25
|
+
return (disp >= 0 ? x << disp : x >>> -disp) >>> 0
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {import('../../vm/vm.js').VM} vm
|
|
30
|
+
* @param {LuaTable} G
|
|
31
|
+
*/
|
|
32
|
+
export function installBit32(vm, G) {
|
|
33
|
+
const bit32 = new LuaTable()
|
|
34
|
+
G.set('bit32', bit32)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {string} name
|
|
38
|
+
* @param {(a: number, b: number) => number} f
|
|
39
|
+
* @param {number} init
|
|
40
|
+
*/
|
|
41
|
+
const fold = function (name, f, init) {
|
|
42
|
+
bit32.set(name, vm.native('bit32.' + name, function (vm2, args) {
|
|
43
|
+
let r = init
|
|
44
|
+
for (let i = 0; i < args.length; i++) r = f(r, u32(args, i, name)) >>> 0
|
|
45
|
+
return r
|
|
46
|
+
}))
|
|
47
|
+
}
|
|
48
|
+
fold('band', function (a, b) { return a & b }, 0xffffffff)
|
|
49
|
+
fold('bor', function (a, b) { return a | b }, 0)
|
|
50
|
+
fold('bxor', function (a, b) { return a ^ b }, 0)
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {any[]} args
|
|
54
|
+
* @param {string} name
|
|
55
|
+
* @returns {[number, number]} field start and width
|
|
56
|
+
*/
|
|
57
|
+
const field = function (args, name) {
|
|
58
|
+
const f = checkNumber(args, 1, name)
|
|
59
|
+
const w = args[2] === undefined ? 1 : checkNumber(args, 2, name)
|
|
60
|
+
if (f < 0) throw argError(2, name, 'field cannot be negative')
|
|
61
|
+
if (w <= 0) throw argError(3, name, 'width must be positive')
|
|
62
|
+
if (f + w > 32) throw fail('trying to access non-existent bits')
|
|
63
|
+
return [ f, w ]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
register(bit32, {
|
|
67
|
+
bnot(vm, args) {
|
|
68
|
+
return ~u32(args, 0, 'bnot') >>> 0
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
btest(vm, args) {
|
|
72
|
+
let r = 0xffffffff
|
|
73
|
+
for (let i = 0; i < args.length; i++) r = (r & u32(args, i, 'btest')) >>> 0
|
|
74
|
+
return r !== 0
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
lshift(vm, args) {
|
|
78
|
+
return shift(u32(args, 0, 'lshift'), Math.floor(checkNumber(args, 1, 'lshift')))
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
rshift(vm, args) {
|
|
82
|
+
return shift(u32(args, 0, 'rshift'), -Math.floor(checkNumber(args, 1, 'rshift')))
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
arshift(vm, args) {
|
|
86
|
+
const x = u32(args, 0, 'arshift')
|
|
87
|
+
const d = Math.floor(checkNumber(args, 1, 'arshift'))
|
|
88
|
+
if (d >= 32) return (x & 0x80000000) !== 0 ? 0xffffffff : 0
|
|
89
|
+
if (d <= -32) return 0
|
|
90
|
+
return d >= 0 ? (x | 0) >> d >>> 0 : shift(x, -d)
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
lrotate(vm, args) {
|
|
94
|
+
const x = u32(args, 0, 'lrotate')
|
|
95
|
+
const r = Math.floor(checkNumber(args, 1, 'lrotate')) & 31
|
|
96
|
+
return r === 0 ? x : ((x << r) | (x >>> (32 - r))) >>> 0
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
rrotate(vm, args) {
|
|
100
|
+
const x = u32(args, 0, 'rrotate')
|
|
101
|
+
const r = Math.floor(checkNumber(args, 1, 'rrotate')) & 31
|
|
102
|
+
return r === 0 ? x : ((x >>> r) | (x << (32 - r))) >>> 0
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
extract(vm, args) {
|
|
106
|
+
const x = u32(args, 0, 'extract')
|
|
107
|
+
const fw = field(args, 'extract')
|
|
108
|
+
return fw[1] === 32 ? x : (x >>> fw[0]) & (Math.pow(2, fw[1]) - 1)
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
replace(vm, args) {
|
|
112
|
+
const x = u32(args, 0, 'replace')
|
|
113
|
+
const v = u32(args, 1, 'replace')
|
|
114
|
+
const f = checkNumber(args, 2, 'replace')
|
|
115
|
+
const w = args[3] === undefined ? 1 : checkNumber(args, 3, 'replace')
|
|
116
|
+
if (f < 0) throw argError(3, 'replace', 'field cannot be negative')
|
|
117
|
+
if (w <= 0) throw argError(4, 'replace', 'width must be positive')
|
|
118
|
+
if (f + w > 32) throw fail('trying to access non-existent bits')
|
|
119
|
+
const mask = w === 32 ? 0xffffffff : Math.pow(2, w) - 1
|
|
120
|
+
return (((x & ~(mask * Math.pow(2, f))) | ((v & mask) << f)) >>> 0)
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
countlz(vm, args) {
|
|
124
|
+
const x = u32(args, 0, 'countlz')
|
|
125
|
+
if (x === 0) return 32
|
|
126
|
+
let n = 0
|
|
127
|
+
for (let bit = 0x80000000; (x & bit) === 0; bit >>>= 1) n++
|
|
128
|
+
return n
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
countrz(vm, args) {
|
|
132
|
+
const x = u32(args, 0, 'countrz')
|
|
133
|
+
if (x === 0) return 32
|
|
134
|
+
let n = 0
|
|
135
|
+
while (((x >>> n) & 1) === 0) n++
|
|
136
|
+
return n
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
byteswap(vm, args) {
|
|
140
|
+
const x = u32(args, 0, 'byteswap')
|
|
141
|
+
return (((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >>> 8) & 0xff00) | (x >>> 24)) >>> 0
|
|
142
|
+
},
|
|
143
|
+
}, 'bit32.')
|
|
144
|
+
}
|
|
@@ -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
|
+
}
|