lecodes-sdk 0.19.2 → 0.20.2
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/dist/global.d.ts +62 -0
- package/dist/host.d.ts +3 -0
- package/dist/types/audio/Bus.d.ts +45 -0
- package/dist/types/audio/Sound.d.ts +28 -0
- package/dist/types/audio/Voice.d.ts +27 -0
- package/dist/types/audio/audio.d.ts +83 -0
- package/dist/types/audio/support.d.ts +1 -0
- package/dist/types/gl/AudioSource.d.ts +60 -0
- package/dist/types/gl/AudioZone.d.ts +32 -0
- package/dist/types/gl/DecalSet.d.ts +103 -0
- package/dist/types/gl/Geometry.d.ts +5 -0
- package/dist/types/gl/Light.d.ts +7 -0
- package/dist/types/gl/Locomotion.d.ts +3 -1
- package/dist/types/gl/Material.d.ts +86 -2
- package/dist/types/gl/Mesh.d.ts +11 -0
- package/dist/types/gl/Scene.d.ts +23 -0
- package/dist/types/gl/SceneAudio.d.ts +11 -0
- package/dist/types/gl/Texture.d.ts +29 -1
- package/dist/types/gl/animation/AnimationClip.d.ts +25 -12
- package/dist/types/gl/animation/Animator.d.ts +51 -183
- package/dist/types/gl/animation/Feet.d.ts +85 -0
- package/dist/types/gl/animation/Warp.d.ts +53 -0
- package/dist/types/gl/animation/core.d.ts +61 -17
- package/dist/types/gl/state.d.ts +0 -1
- package/dist/types/inject.d.ts +17 -2
- package/dist/types/plugins/map.d.ts +174 -0
- package/dist/types/runtime/input.d.ts +11 -0
- package/dist/types/ui/UIImage.d.ts +15 -5
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/src/audio/Bus.ts +102 -0
- package/src/audio/Sound.ts +96 -0
- package/src/audio/Voice.ts +102 -0
- package/src/audio/audio.ts +161 -0
- package/src/audio/support.ts +6 -0
- package/src/bridges.d.ts +1481 -1345
- package/src/compile/__tests__/compile.test.ts +12 -0
- package/src/compile/compileProject.ts +35 -15
- package/src/compile/index.ts +3 -0
- package/src/core/Aspect.ts +34 -9
- package/src/g2/Scene2D.ts +7 -0
- package/src/gl/AudioSource.ts +113 -0
- package/src/gl/AudioZone.ts +75 -0
- package/src/gl/DecalSet.ts +233 -0
- package/src/gl/Geometry.ts +5 -0
- package/src/gl/Light.ts +16 -0
- package/src/gl/Lightmap.ts +3 -2
- package/src/gl/Locomotion.ts +7 -5
- package/src/gl/Material.ts +152 -4
- package/src/gl/Mesh.ts +20 -1
- package/src/gl/Particles.ts +3 -3
- package/src/gl/Scene.ts +42 -8
- package/src/gl/SceneAudio.ts +26 -0
- package/src/gl/Texture.ts +43 -3
- package/src/gl/Vehicle.ts +5 -5
- package/src/gl/animation/AnimationClip.ts +43 -20
- package/src/gl/animation/Animator.ts +138 -329
- package/src/gl/animation/Feet.ts +134 -0
- package/src/gl/animation/Loop.ts +3 -1
- package/src/gl/animation/Warp.ts +96 -0
- package/src/gl/animation/core.ts +741 -670
- package/src/gl/state.ts +6 -6
- package/src/host.d.ts +3 -0
- package/src/inject.ts +23 -2
- package/src/plugins/map.ts +396 -0
- package/src/runtime/input.ts +6 -1
- package/src/ui/UIImage.ts +21 -7
package/src/bridges.d.ts
CHANGED
|
@@ -1,1345 +1,1481 @@
|
|
|
1
|
-
// The host ABI. These four objects are injected onto the global scope by the runtime host
|
|
2
|
-
// (web viewer, desktop, iOS) before any user/SDK code runs. The SDK is a thin, typed re-skin over
|
|
3
|
-
// them — it never bundles them; it only references them as free globals. Faithfully tracks the
|
|
4
|
-
// surface in packages/worker/src/global.d.ts (the proven contract).
|
|
5
|
-
|
|
6
|
-
declare global {
|
|
7
|
-
|
|
8
|
-
// ---- 3D engine (Filament / creator-gl) -------------------------------------------------------
|
|
9
|
-
var _creator: {
|
|
10
|
-
backend: string
|
|
11
|
-
|
|
12
|
-
createScene(): number
|
|
13
|
-
createOverlayScene(sceneId: number): number
|
|
14
|
-
createGLView(): void
|
|
15
|
-
openScene(sceneId: number): void
|
|
16
|
-
closeScene(): void
|
|
17
|
-
launchAR(sceneId: number, onComplete: () => void, onReject: () => void): void
|
|
18
|
-
stopAR(): void
|
|
19
|
-
launchVR(sceneId: number, onComplete: () => void, onReject: (err?: unknown) => void): void
|
|
20
|
-
stopVR(): void
|
|
21
|
-
addEntityToScene(sceneId: number, entityId: number): void
|
|
22
|
-
removeEntityFromScene(sceneId: number, entityId: number): void
|
|
23
|
-
getSceneMaterial(sceneId: number): number
|
|
24
|
-
warmRender(sceneId: number, onComplete: () => void): void
|
|
25
|
-
|
|
26
|
-
createEntity(): number
|
|
27
|
-
cloneEntity(entityId: number): number
|
|
28
|
-
destroyEntity(entityId: number): void
|
|
29
|
-
|
|
30
|
-
setMatrix(entityId: number, mat: Float32Array): void
|
|
31
|
-
setWorldMatrix(entityId: number, mat: Float32Array): void
|
|
32
|
-
getChildren(entityId: number): number[]
|
|
33
|
-
getChildCount(entityId: number): number
|
|
34
|
-
getChild(entityId: number, index: number): number
|
|
35
|
-
|
|
36
|
-
setPosition(entityId: number, x: number, y: number, z: number): void
|
|
37
|
-
setQuaternion(entityId: number, x: number, y: number, z: number, w: number): void
|
|
38
|
-
setEulerAngles(entityId: number, x: number, y: number, z: number, order: number): void
|
|
39
|
-
setScale(entityId: number, x: number, y: number, z: number): void
|
|
40
|
-
|
|
41
|
-
addChildren(parentEntityId: number, entityIds: number[]): void
|
|
42
|
-
setParent(entityId: number, parentEntityId: number, worldPositionStays: boolean): void
|
|
43
|
-
setParentNull(entityId: number, worldPositionStays: boolean): void
|
|
44
|
-
getParent(entityId: number): number
|
|
45
|
-
traverse(entityId: number, callback: (entityId: number) => void): void
|
|
46
|
-
/** Descendant of `entityId` by name, with the Animator's binding rule: exact name first, then the
|
|
47
|
-
* short name (after the last `:` / `|` — Mixamo `mixamorig:Hips`); a skin joint beats a plain node
|
|
48
|
-
* of the same name (merged GLBs carrying a leftover skeleton copy), otherwise first in tree order.
|
|
49
|
-
* 0 when absent. Optional: hosts that predate it fall back to the SDK's traverse walk (node.bone). */
|
|
50
|
-
findNode?(entityId: number, name: string): number
|
|
51
|
-
|
|
52
|
-
createSunLight(entityId: number, x: number, y: number, z: number, intensity: number, color: number, shadowsQuality: number, shadowDistance: number): void
|
|
53
|
-
/** Punctual light. `intensity` is luminous POWER in lumens; `falloff` is the metres of
|
|
54
|
-
* influence (filament's own default is 1 m, i.e. invisible, so it is always passed). */
|
|
55
|
-
createPointLight?(entityId: number, intensity: number, color: number, falloff: number, castShadows: boolean): void
|
|
56
|
-
/** Live intensity for any light (sun: lux, point: lumens) — a flash animates instead of rebuilding. */
|
|
57
|
-
setLightIntensity?(entityId: number, intensity: number): void
|
|
58
|
-
setLightColor?(entityId: number, color: number): void
|
|
59
|
-
/** `iblFetchId` (optional, -1 = none) names the scene's own probe; without it the host looks for a project-wide `ibl.ktx`. */
|
|
60
|
-
setDefaultIbl(sceneId: number, intensity: number, iblFetchId?: number): void
|
|
61
|
-
setBloomOptions(sceneId: number, enabled: boolean, strength: number, quality: number): void
|
|
62
|
-
setToneMapping?(sceneId: number, mode: number): void
|
|
63
|
-
/** Exposure of the scene's camera — filament's physical model: `aperture` f-stops,
|
|
64
|
-
* `shutterSpeed` seconds, `sensitivity` ISO (default f/16, 1/125 s, ISO 100 = EV100 15, bright
|
|
65
|
-
* sunlight). ISO ×2 = one stop brighter. Scene-referred light follows it; particle emission is
|
|
66
|
-
* post-exposure and does not. Optional: hosts that predate it keep the fixed default. */
|
|
67
|
-
setCameraExposure?(sceneId: number, aperture: number, shutterSpeed: number, sensitivity: number): void
|
|
68
|
-
/** Display output range (macOS/iOS EDR, `device.hdr`). `getDisplayHeadroom` is what the engine
|
|
69
|
-
* renders to right now: the screen's peak as a multiple of SDR white, quantised to half-stops;
|
|
70
|
-
* 0 or 1 = SDR. Live — it ramps up from 1 over the first seconds, follows brightness and the
|
|
71
|
-
* screen under the window. `getDisplayMaxHeadroom` is the peak the surface can reach at all
|
|
72
|
-
* (1 = SDR), constant once the surface exists: the value to branch content on. Optional: hosts
|
|
73
|
-
* that predate it, or render 8-bit, are SDR. */
|
|
74
|
-
getDisplayHeadroom?(): number
|
|
75
|
-
getDisplayMaxHeadroom?(): number
|
|
76
|
-
/** HDR look, engine-wide (creator.h `setHdrStrength` / `setHdrPaperWhite`): `strength` 0..1 =
|
|
77
|
-
* how much of the picture reaches for the headroom (0 only what SDR clipped, 1 nearly
|
|
78
|
-
* everything), `paperWhite` 1..8 = where the operator's white lands as a multiple of SDR white
|
|
79
|
-
* (the "HDR brightness" of a console calibration screen; clamped to the headroom). A host may
|
|
80
|
-
* pin either from its environment — the getters report what is in force. Optional. */
|
|
81
|
-
setHdrStrength?(strength: number): void
|
|
82
|
-
getHdrStrength?(): number
|
|
83
|
-
setHdrPaperWhite?(paperWhite: number): void
|
|
84
|
-
getHdrPaperWhite?(): number
|
|
85
|
-
/** Screen-space ambient occlusion: the contact darkening in creases and where objects meet the
|
|
86
|
-
* ground. `radius` is world-space metres, `power` the falloff contrast, `quality` 0 LOW … 3
|
|
87
|
-
* ULTRA (sample count — not the buffer resolution, which stays half-res).
|
|
88
|
-
* Optional: hosts that predate it render without AO and the SDK skips the call. */
|
|
89
|
-
setAmbientOcclusionOptions?(sceneId: number, enabled: boolean, intensity: number, radius: number, power: number, quality: number): void
|
|
90
|
-
/** Distance fog / aerial perspective. `color` is packed 0xRRGGBB used as a TINT on the
|
|
91
|
-
* in-scattered ambient — the engine multiplies it by the environment luminance, so white means
|
|
92
|
-
* "as bright as the ambient" and it is NOT the absolute-radiance convention `setSkybox` uses.
|
|
93
|
-
* `density` = extinction per metre at `height`, `heightFalloff` 1/m (0 = uniform),
|
|
94
|
-
* `cutOff` <= 0 = apply at every distance (the skybox included — that is what blends the
|
|
95
|
-
* horizon), `fromIbl` = take the colour from the environment in the view direction and tint
|
|
96
|
-
* it by `color`.
|
|
97
|
-
* Optional: hosts that predate it render without fog and the SDK skips the call. */
|
|
98
|
-
setFogOptions?(sceneId: number, enabled: boolean, color: number, distance: number, density: number, height: number, heightFalloff: number, maxOpacity: number, cutOff: number, fromIbl: boolean): void
|
|
99
|
-
setSkybox(sceneId: number, color: number): void
|
|
100
|
-
/** Draw the scene's IBL environment as the sky instead of a flat colour. No-op until the IBL
|
|
101
|
-
* exists (setDefaultIbl runs first). Optional: hosts that predate it keep the flat skybox. */
|
|
102
|
-
setSkyboxFromEnvironment?(sceneId: number): void
|
|
103
|
-
/** The sky from its own KTX1 cubemap. `fetchId` is a local-resource id (`_creatorUtils.fetchLocal`
|
|
104
|
-
* / an `asset()` handle), pointing at cmgen's `<name>_skybox.ktx` — the sharp single-mip file,
|
|
105
|
-
* not the roughness-prefiltered `_ibl.ktx` beside it. Optional: hosts that predate it keep the
|
|
106
|
-
* flat skybox. */
|
|
107
|
-
setSkyboxTexture?(sceneId: number, fetchId: number): void
|
|
108
|
-
setSceneMultiSampleAntiAliasing(sceneId: number, enabled: boolean, scale: number): void
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
*
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
*
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
//
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
// the
|
|
269
|
-
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
//
|
|
280
|
-
//
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
//
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
//
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
//
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
//
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
|
|
336
|
-
//
|
|
337
|
-
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
//
|
|
344
|
-
|
|
345
|
-
//
|
|
346
|
-
|
|
347
|
-
//
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
//
|
|
351
|
-
//
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
//
|
|
356
|
-
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
//
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
//
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
//
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
//
|
|
370
|
-
|
|
371
|
-
//
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
//
|
|
376
|
-
//
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
//
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
//
|
|
383
|
-
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
//
|
|
387
|
-
//
|
|
388
|
-
//
|
|
389
|
-
//
|
|
390
|
-
|
|
391
|
-
//
|
|
392
|
-
|
|
393
|
-
//
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
//
|
|
406
|
-
//
|
|
407
|
-
//
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
//
|
|
412
|
-
//
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
//
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
//
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
//
|
|
432
|
-
//
|
|
433
|
-
|
|
434
|
-
//
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
//
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
*
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
*
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
/**
|
|
527
|
-
*
|
|
528
|
-
* `
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
//
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
*
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
*
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
//
|
|
578
|
-
//
|
|
579
|
-
// SDK
|
|
580
|
-
//
|
|
581
|
-
//
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
*
|
|
594
|
-
|
|
595
|
-
/**
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
//
|
|
608
|
-
//
|
|
609
|
-
//
|
|
610
|
-
//
|
|
611
|
-
//
|
|
612
|
-
//
|
|
613
|
-
//
|
|
614
|
-
//
|
|
615
|
-
//
|
|
616
|
-
//
|
|
617
|
-
//
|
|
618
|
-
//
|
|
619
|
-
//
|
|
620
|
-
//
|
|
621
|
-
//
|
|
622
|
-
//
|
|
623
|
-
//
|
|
624
|
-
//
|
|
625
|
-
//
|
|
626
|
-
//
|
|
627
|
-
//
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
/**
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
//
|
|
670
|
-
//
|
|
671
|
-
//
|
|
672
|
-
//
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
//
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
//
|
|
837
|
-
//
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
/**
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
/**
|
|
866
|
-
*
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
/**
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
/**
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
/**
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
/**
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
/**
|
|
935
|
-
|
|
936
|
-
/**
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
//
|
|
1095
|
-
//
|
|
1096
|
-
//
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
//
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
//
|
|
1103
|
-
//
|
|
1104
|
-
//
|
|
1105
|
-
//
|
|
1106
|
-
//
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
//
|
|
1128
|
-
//
|
|
1129
|
-
//
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
//
|
|
1143
|
-
//
|
|
1144
|
-
//
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
//
|
|
1176
|
-
//
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
/**
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
*
|
|
1244
|
-
* the
|
|
1245
|
-
*
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
*
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
*
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
*
|
|
1285
|
-
*
|
|
1286
|
-
*
|
|
1287
|
-
*
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
*
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1
|
+
// The host ABI. These four objects are injected onto the global scope by the runtime host
|
|
2
|
+
// (web viewer, desktop, iOS) before any user/SDK code runs. The SDK is a thin, typed re-skin over
|
|
3
|
+
// them — it never bundles them; it only references them as free globals. Faithfully tracks the
|
|
4
|
+
// surface in packages/worker/src/global.d.ts (the proven contract).
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
|
|
8
|
+
// ---- 3D engine (Filament / creator-gl) -------------------------------------------------------
|
|
9
|
+
var _creator: {
|
|
10
|
+
backend: string
|
|
11
|
+
|
|
12
|
+
createScene(): number
|
|
13
|
+
createOverlayScene(sceneId: number): number
|
|
14
|
+
createGLView(): void
|
|
15
|
+
openScene(sceneId: number): void
|
|
16
|
+
closeScene(): void
|
|
17
|
+
launchAR(sceneId: number, onComplete: () => void, onReject: () => void): void
|
|
18
|
+
stopAR(): void
|
|
19
|
+
launchVR(sceneId: number, onComplete: () => void, onReject: (err?: unknown) => void): void
|
|
20
|
+
stopVR(): void
|
|
21
|
+
addEntityToScene(sceneId: number, entityId: number): void
|
|
22
|
+
removeEntityFromScene(sceneId: number, entityId: number): void
|
|
23
|
+
getSceneMaterial(sceneId: number): number
|
|
24
|
+
warmRender(sceneId: number, onComplete: () => void): void
|
|
25
|
+
|
|
26
|
+
createEntity(): number
|
|
27
|
+
cloneEntity(entityId: number): number
|
|
28
|
+
destroyEntity(entityId: number): void
|
|
29
|
+
|
|
30
|
+
setMatrix(entityId: number, mat: Float32Array): void
|
|
31
|
+
setWorldMatrix(entityId: number, mat: Float32Array): void
|
|
32
|
+
getChildren(entityId: number): number[]
|
|
33
|
+
getChildCount(entityId: number): number
|
|
34
|
+
getChild(entityId: number, index: number): number
|
|
35
|
+
|
|
36
|
+
setPosition(entityId: number, x: number, y: number, z: number): void
|
|
37
|
+
setQuaternion(entityId: number, x: number, y: number, z: number, w: number): void
|
|
38
|
+
setEulerAngles(entityId: number, x: number, y: number, z: number, order: number): void
|
|
39
|
+
setScale(entityId: number, x: number, y: number, z: number): void
|
|
40
|
+
|
|
41
|
+
addChildren(parentEntityId: number, entityIds: number[]): void
|
|
42
|
+
setParent(entityId: number, parentEntityId: number, worldPositionStays: boolean): void
|
|
43
|
+
setParentNull(entityId: number, worldPositionStays: boolean): void
|
|
44
|
+
getParent(entityId: number): number
|
|
45
|
+
traverse(entityId: number, callback: (entityId: number) => void): void
|
|
46
|
+
/** Descendant of `entityId` by name, with the Animator's binding rule: exact name first, then the
|
|
47
|
+
* short name (after the last `:` / `|` — Mixamo `mixamorig:Hips`); a skin joint beats a plain node
|
|
48
|
+
* of the same name (merged GLBs carrying a leftover skeleton copy), otherwise first in tree order.
|
|
49
|
+
* 0 when absent. Optional: hosts that predate it fall back to the SDK's traverse walk (node.bone). */
|
|
50
|
+
findNode?(entityId: number, name: string): number
|
|
51
|
+
|
|
52
|
+
createSunLight(entityId: number, x: number, y: number, z: number, intensity: number, color: number, shadowsQuality: number, shadowDistance: number): void
|
|
53
|
+
/** Punctual light. `intensity` is luminous POWER in lumens; `falloff` is the metres of
|
|
54
|
+
* influence (filament's own default is 1 m, i.e. invisible, so it is always passed). */
|
|
55
|
+
createPointLight?(entityId: number, intensity: number, color: number, falloff: number, castShadows: boolean): void
|
|
56
|
+
/** Live intensity for any light (sun: lux, point: lumens) — a flash animates instead of rebuilding. */
|
|
57
|
+
setLightIntensity?(entityId: number, intensity: number): void
|
|
58
|
+
setLightColor?(entityId: number, color: number): void
|
|
59
|
+
/** `iblFetchId` (optional, -1 = none) names the scene's own probe; without it the host looks for a project-wide `ibl.ktx`. */
|
|
60
|
+
setDefaultIbl(sceneId: number, intensity: number, iblFetchId?: number): void
|
|
61
|
+
setBloomOptions(sceneId: number, enabled: boolean, strength: number, quality: number): void
|
|
62
|
+
setToneMapping?(sceneId: number, mode: number): void
|
|
63
|
+
/** Exposure of the scene's camera — filament's physical model: `aperture` f-stops,
|
|
64
|
+
* `shutterSpeed` seconds, `sensitivity` ISO (default f/16, 1/125 s, ISO 100 = EV100 15, bright
|
|
65
|
+
* sunlight). ISO ×2 = one stop brighter. Scene-referred light follows it; particle emission is
|
|
66
|
+
* post-exposure and does not. Optional: hosts that predate it keep the fixed default. */
|
|
67
|
+
setCameraExposure?(sceneId: number, aperture: number, shutterSpeed: number, sensitivity: number): void
|
|
68
|
+
/** Display output range (macOS/iOS EDR, `device.hdr`). `getDisplayHeadroom` is what the engine
|
|
69
|
+
* renders to right now: the screen's peak as a multiple of SDR white, quantised to half-stops;
|
|
70
|
+
* 0 or 1 = SDR. Live — it ramps up from 1 over the first seconds, follows brightness and the
|
|
71
|
+
* screen under the window. `getDisplayMaxHeadroom` is the peak the surface can reach at all
|
|
72
|
+
* (1 = SDR), constant once the surface exists: the value to branch content on. Optional: hosts
|
|
73
|
+
* that predate it, or render 8-bit, are SDR. */
|
|
74
|
+
getDisplayHeadroom?(): number
|
|
75
|
+
getDisplayMaxHeadroom?(): number
|
|
76
|
+
/** HDR look, engine-wide (creator.h `setHdrStrength` / `setHdrPaperWhite`): `strength` 0..1 =
|
|
77
|
+
* how much of the picture reaches for the headroom (0 only what SDR clipped, 1 nearly
|
|
78
|
+
* everything), `paperWhite` 1..8 = where the operator's white lands as a multiple of SDR white
|
|
79
|
+
* (the "HDR brightness" of a console calibration screen; clamped to the headroom). A host may
|
|
80
|
+
* pin either from its environment — the getters report what is in force. Optional. */
|
|
81
|
+
setHdrStrength?(strength: number): void
|
|
82
|
+
getHdrStrength?(): number
|
|
83
|
+
setHdrPaperWhite?(paperWhite: number): void
|
|
84
|
+
getHdrPaperWhite?(): number
|
|
85
|
+
/** Screen-space ambient occlusion: the contact darkening in creases and where objects meet the
|
|
86
|
+
* ground. `radius` is world-space metres, `power` the falloff contrast, `quality` 0 LOW … 3
|
|
87
|
+
* ULTRA (sample count — not the buffer resolution, which stays half-res).
|
|
88
|
+
* Optional: hosts that predate it render without AO and the SDK skips the call. */
|
|
89
|
+
setAmbientOcclusionOptions?(sceneId: number, enabled: boolean, intensity: number, radius: number, power: number, quality: number): void
|
|
90
|
+
/** Distance fog / aerial perspective. `color` is packed 0xRRGGBB used as a TINT on the
|
|
91
|
+
* in-scattered ambient — the engine multiplies it by the environment luminance, so white means
|
|
92
|
+
* "as bright as the ambient" and it is NOT the absolute-radiance convention `setSkybox` uses.
|
|
93
|
+
* `density` = extinction per metre at `height`, `heightFalloff` 1/m (0 = uniform),
|
|
94
|
+
* `cutOff` <= 0 = apply at every distance (the skybox included — that is what blends the
|
|
95
|
+
* horizon), `fromIbl` = take the colour from the environment in the view direction and tint
|
|
96
|
+
* it by `color`.
|
|
97
|
+
* Optional: hosts that predate it render without fog and the SDK skips the call. */
|
|
98
|
+
setFogOptions?(sceneId: number, enabled: boolean, color: number, distance: number, density: number, height: number, heightFalloff: number, maxOpacity: number, cutOff: number, fromIbl: boolean): void
|
|
99
|
+
setSkybox(sceneId: number, color: number): void
|
|
100
|
+
/** Draw the scene's IBL environment as the sky instead of a flat colour. No-op until the IBL
|
|
101
|
+
* exists (setDefaultIbl runs first). Optional: hosts that predate it keep the flat skybox. */
|
|
102
|
+
setSkyboxFromEnvironment?(sceneId: number): void
|
|
103
|
+
/** The sky from its own KTX1 cubemap. `fetchId` is a local-resource id (`_creatorUtils.fetchLocal`
|
|
104
|
+
* / an `asset()` handle), pointing at cmgen's `<name>_skybox.ktx` — the sharp single-mip file,
|
|
105
|
+
* not the roughness-prefiltered `_ibl.ktx` beside it. Optional: hosts that predate it keep the
|
|
106
|
+
* flat skybox. */
|
|
107
|
+
setSkyboxTexture?(sceneId: number, fetchId: number): void
|
|
108
|
+
setSceneMultiSampleAntiAliasing(sceneId: number, enabled: boolean, scale: number): void
|
|
109
|
+
/** Filament View::setStencilBufferEnabled (Scene.stencil). Optional. */
|
|
110
|
+
setSceneStencil?(sceneId: number, enabled: boolean): void
|
|
111
|
+
/** Render resolution: `renderScale` (0.25–1) = fixed 3D-buffer scale vs the viewport (the UI is
|
|
112
|
+
* untouched; a host that owns the 3D texture resizes it, one rendering into the swapchain may
|
|
113
|
+
* ignore it), `dynamicResolution` = engine-adaptive scaling under that down to `minScale`.
|
|
114
|
+
* Optional: older hosts predate it and the SDK skips the call. */
|
|
115
|
+
setSceneRenderOptions?(sceneId: number, renderScale: number, dynamicResolution: boolean, minScale: number): void
|
|
116
|
+
/** Anisotropic filtering for every texture bound FROM HERE ON (1 = off, 2 = the engine default,
|
|
117
|
+
* 16 = max; clamped). Engine-wide rather than per scene, because a sampler is baked when its
|
|
118
|
+
* texture is bound — a glTF binds during `Model.load`, and two scenes cannot disagree about a
|
|
119
|
+
* texture they share. Call it before loading the assets it should apply to; `SceneOptions.
|
|
120
|
+
* anisotropy` does that automatically (a scene's env runs before its nodes build). Optional:
|
|
121
|
+
* hosts that predate it keep isotropic filtering and the SDK skips the call. */
|
|
122
|
+
setTextureAnisotropy?(level: number): void
|
|
123
|
+
/** Engine-wide cap on texture size (`Texture.maxSize` / `SceneOptions.maxTextureSize`): a
|
|
124
|
+
* KTX2 wider or taller than `size` loses its top mip levels on load, a glTF PNG/JPEG is
|
|
125
|
+
* downsampled; 0 = no cap. Reaches textures created AFTER the call — a loaded level keeps
|
|
126
|
+
* its textures, so a settings menu applies it on the next level load. `createTexture` flag
|
|
127
|
+
* 2 (FULL_SIZE) exempts one texture (lightmap pages). Optional: hosts that predate it load
|
|
128
|
+
* full-size textures and the SDK skips the call. */
|
|
129
|
+
setTextureMaxSize?(size: number): void
|
|
130
|
+
/** Depth-reading effects on / off (`scene.setDepthEffects`): soft particles (`depthFade`) and
|
|
131
|
+
* projected decals read the scene depth, which costs a half-res depth pre-pass of every opaque
|
|
132
|
+
* draw. Off = no pre-pass, hard-edged particles, decal sets draw nothing. Engine-wide, live.
|
|
133
|
+
* Optional: hosts that predate it keep the effects and the SDK skips the call. */
|
|
134
|
+
setDepthEffects?(enabled: boolean): void
|
|
135
|
+
/** LOD distance (`scene.setLodBias`): the LOD pass' screen-size thresholds × `bias` — 2 = every
|
|
136
|
+
* level switches at half the distance, 0.5 = full detail twice as far; 1 = the defaults
|
|
137
|
+
* (0.30 / 0.12 / 0.05 of the viewport height). Engine-wide, live, clamped 0.25..8. Optional:
|
|
138
|
+
* hosts without the LOD pass ignore it and the SDK skips the call. */
|
|
139
|
+
setLodBias?(bias: number): void
|
|
140
|
+
setMaterialGlobalParameter(sceneId: number, i: number, x: number, y: number, z: number, w: number): void
|
|
141
|
+
getCameraFov(sceneId: number, fovType: number): number
|
|
142
|
+
/** The scene camera's projection: VERTICAL fov in degrees + near/far clip distances (defaults
|
|
143
|
+
* 60 / 0.01 / 1000). Aspect stays host-owned — the host STORES these per scene and re-applies
|
|
144
|
+
* them whenever the viewport changes, so one call outlives every resize. Optional: hosts that
|
|
145
|
+
* predate it keep the fixed defaults and the SDK feature-detects (Camera.setProjection). */
|
|
146
|
+
setCameraProjection?(sceneId: number, fov: number, near: number, far: number): void
|
|
147
|
+
|
|
148
|
+
getMatrix(entityId: number, mat: Float32Array): boolean
|
|
149
|
+
getWorldMatrix(entityId: number, mat: Float32Array): void
|
|
150
|
+
getWorldPosition(entityId: number, mat: Float32Array): void
|
|
151
|
+
getWorldDirection(entityId: number, mode: number, mat: Float32Array): void
|
|
152
|
+
|
|
153
|
+
getWorldMatrixInverse(entityId: number, mat: Float32Array): void
|
|
154
|
+
getCameraViewDirection(sceneId: number, screenX: number, screenY: number, mat: Float32Array): void
|
|
155
|
+
|
|
156
|
+
/** `uv1` (optional, 2 floats per vertex) is the lightmap UV set (Geometry.uv1); absent → the
|
|
157
|
+
* host duplicates `uv` into UV1. Hosts that predate the argument ignore it. */
|
|
158
|
+
/** `colors` (Geometry.colors) is 4 bytes RGBA per vertex for a `requires: [color]` material;
|
|
159
|
+
* a host that predates it draws the mesh white. */
|
|
160
|
+
setMesh(entityId: number, materialId: number, vertices: Float32Array, normals: Float32Array, indices: Uint16Array, uv: Float32Array, meshType: number, uv1?: Float32Array, colors?: Uint8Array): void
|
|
161
|
+
// Terrain (gl/Terrain.ts ↔ creator-gl/src/terrain.cpp, docs/terrain-plan.md §1.4): a heightmap grid of
|
|
162
|
+
// sizeX × sizeZ samples `cellSize` apart (+X across columns, +Z across rows, height on +Y, sample 0 at
|
|
163
|
+
// the node origin), drawn as one renderable per `chunk`×`chunk` cells on internal children of the
|
|
164
|
+
// entity (u16 indices → chunk ≤ 255). `holes` = one byte per sample, 1 = hole (a triangle exists only
|
|
165
|
+
// when its three samples are valid — the same rule as the Jolt height field), null = none. UV0 = local
|
|
166
|
+
// XZ in metres, UV1 = the terrain's unit square. Returns the chunk count (0 = refused). terrainUpdate
|
|
167
|
+
// re-reads the FULL arrays and rebuilds the chunks the sample rectangle touches. All optional: a host
|
|
168
|
+
// without them gets the SDK's own chunk meshes through setMesh (gl/terrainMesh.ts).
|
|
169
|
+
terrainCreate?(entityId: number, materialId: number, heights: Float32Array, sizeX: number, sizeZ: number, cellSize: number, chunk: number, holes: Uint8Array | null): number
|
|
170
|
+
terrainUpdate?(entityId: number, heights: Float32Array, holes: Uint8Array | null, x0: number, z0: number, w: number, h: number): void
|
|
171
|
+
terrainSetMaterial?(entityId: number, materialId: number): void
|
|
172
|
+
terrainSetShadows?(entityId: number, cast: boolean, receive: boolean): void
|
|
173
|
+
// Instanced mesh (gl/InstancedMesh.ts ↔ creator-gl/src/instanced.cpp): `count` transforms,
|
|
174
|
+
// column-major 4×4 local to the node, all-zero = hidden. setInstanceTransforms writes
|
|
175
|
+
// matrices.length / 16 of them starting at `first` (a subarray view is fine — consumed synchronously).
|
|
176
|
+
createInstancedMesh(entityId: number, materialId: number, vertices: Float32Array, normals: Float32Array, indices: Uint16Array, uv: Float32Array, count: number): void
|
|
177
|
+
setInstanceTransforms(entityId: number, matrices: Float32Array, first: number): void
|
|
178
|
+
setInstancedMeshMaterial(entityId: number, materialId: number): void
|
|
179
|
+
setInstancedMeshShadows(entityId: number, cast: boolean, receive: boolean): void
|
|
180
|
+
setCulling(entityId: number, culling: boolean): void
|
|
181
|
+
/** Filament RenderableManager::setPriority — the coarse draw order, 0..7 (Mesh.renderPriority).
|
|
182
|
+
* Optional: an older host leaves everything at the default 4. */
|
|
183
|
+
setRenderPriority?(entityId: number, priority: number): void
|
|
184
|
+
/** Filament MaterialInstance::setDepthCulling / setDepthWrite — per-instance overrides of the
|
|
185
|
+
* depth state baked into the shader package (Material.depthTest / depthWrite). Optional. */
|
|
186
|
+
setMaterialDepthTest?(materialInstanceId: number, enable: boolean): void
|
|
187
|
+
setMaterialDepthWrite?(materialInstanceId: number, enable: boolean): void
|
|
188
|
+
/** Filament MaterialInstance::setCullingMode: 0 none (double-sided), 1 front, 2 back. Optional. */
|
|
189
|
+
setMaterialCulling?(materialInstanceId: number, mode: number): void
|
|
190
|
+
/** Filament MaterialInstance stencil state in one call (Material.stencil): `test` 0 always, 1 never,
|
|
191
|
+
* 2 less, 3 lessEqual, 4 greater, 5 greaterEqual, 6 equal, 7 notEqual; the ops 0 keep, 1 zero,
|
|
192
|
+
* 2 replace, 3 increment, 4 decrement, 5 invert. Optional. */
|
|
193
|
+
setMaterialStencil?(materialInstanceId: number, write: boolean, test: number, ref: number, onPass: number, onFail: number, onDepthFail: number, readMask: number, writeMask: number): void
|
|
194
|
+
setCastShadows(entityId: number, culling: boolean): void
|
|
195
|
+
setReceiveShadows(entityId: number, culling: boolean): void
|
|
196
|
+
|
|
197
|
+
/** Decode a fetched image into a texture. `flags` (optional, Texture.load): bit 1 = LINEAR data
|
|
198
|
+
* (a normal map — store RGBA8, not sRGB); unset / absent = colour, sRGB. A host that ignores
|
|
199
|
+
* it loads colour correctly and normal maps wrongly. KTX2 decides by its own header. */
|
|
200
|
+
createTexture(systemId: number, onComplete: (id: number, width: number, height: number) => void, onReject: () => void, flags?: number): void
|
|
201
|
+
// Texture from a baked _creatorCanvas surface (RGBA8, already rasterized — synchronous, no decode).
|
|
202
|
+
createTextureFromCanvas(surfaceId: number): number
|
|
203
|
+
updateTextureFromCanvas(texId: number, surfaceId: number): void
|
|
204
|
+
/** A texture from raw UBYTE pixels — `channels` 1–4, row-major, `width*height*channels` bytes, no
|
|
205
|
+
* mips; `srgb` selects the sRGB internal format for 3/4 channels (colour) vs linear (data — a
|
|
206
|
+
* terrain's control map). The bytes are copied. Returns 0xFFFFFFFF on failure. `updateTexturePixels`
|
|
207
|
+
* re-uploads a sub-rectangle with the creation channel count. Optional (Texture.fromPixels throws). */
|
|
208
|
+
createTexturePixels?(width: number, height: number, channels: number, data: Uint8Array, srgb: boolean): number
|
|
209
|
+
updateTexturePixels?(textureId: number, x: number, y: number, width: number, height: number, data: Uint8Array): void
|
|
210
|
+
|
|
211
|
+
createMaterial(systemId: number): number
|
|
212
|
+
createMaterialS(name: string): number
|
|
213
|
+
setMaterial(entityId: number, materialId: number, index: number): void
|
|
214
|
+
getMaterial(entityId: number, index: number): number
|
|
215
|
+
|
|
216
|
+
setUniformRgb(materialId: number, uniform: string, color: number): void
|
|
217
|
+
setUniformRgba(materialId: number, uniform: string, color: number): void
|
|
218
|
+
setUniformFloat(materialId: number, uniform: string, value: number): void
|
|
219
|
+
setUniformBoolean(materialId: number, uniform: string, value: boolean): void
|
|
220
|
+
setUniformTexture(materialId: number, uniform: string, systemId: number, wrapS: number, wrapT: number): void
|
|
221
|
+
setUniformArray(materialId: number, uniform: string, value: Float32Array): void
|
|
222
|
+
setUniformNull(materialId: number, uniform: string): void
|
|
223
|
+
|
|
224
|
+
attachCameraToAR(sceneId: number, cameraEntityId: number, onProjectionChange: (mat: Float32Array, fov: number) => void): void
|
|
225
|
+
getDisplaySize(): Float32Array
|
|
226
|
+
|
|
227
|
+
setVisible(entityId: number, visible: boolean): void
|
|
228
|
+
isVisible(entityId: number): boolean
|
|
229
|
+
|
|
230
|
+
createGlb(systemId: number, onComplete: (buff: number) => void, onReject: () => void): void
|
|
231
|
+
setGlbCulling(entityId: number, culling: boolean): void
|
|
232
|
+
/** Optional. True when the host refits a skinned model's frustum-culling bounds to its joints every
|
|
233
|
+
* frame (creator-gl animation/skinning.cpp), i.e. culling is safe for animated GLBs. Model.load
|
|
234
|
+
* defaults culling ON only where this returns true; absent / false = the always-draw default. */
|
|
235
|
+
skinnedCullingSupported?(): boolean
|
|
236
|
+
/** Optional. Level-of-detail override for a GLB instance (docs/lod-plan.md): `mesh` / `anim` are -1 for
|
|
237
|
+
* automatic (the engine picks by screen size and visibility) or a forced level 0..3. Backs Model.lod
|
|
238
|
+
* and Animator.lod; a host without it (no LOD pass) leaves everything at full detail. */
|
|
239
|
+
setLod?(entityId: number, mesh: number, anim: number): void
|
|
240
|
+
|
|
241
|
+
// Render-synced aspect update(dt) dispatch, called from inside render(). Early = before the physics
|
|
242
|
+
// step; late = after animations/particles, just before draw. Single-slot per phase (the SDK's Aspect
|
|
243
|
+
// dispatcher registers one callback per phase that iterates its ordered updater list).
|
|
244
|
+
setEarlyUpdate(cb: (dt: number) => void): void
|
|
245
|
+
setLateUpdate(cb: (dt: number) => void): void
|
|
246
|
+
/** FIXED phase - the SDK's `updateFixed`: once per physics substep with dt = 1/60 exactly, BEFORE
|
|
247
|
+
* that substep's Jolt step (move commands / velocities written here feed the same step). Under
|
|
248
|
+
* `setTimeScale` the NUMBER of substeps changes, never the dt; at most 4 per frame. `null` clears it -
|
|
249
|
+
* registered lazily, only once an aspect declares the phase (one flag check per substep otherwise).
|
|
250
|
+
* Optional: a host without it gets the SDK's own 1/60 accumulator inside the early phase. */
|
|
251
|
+
setFixedUpdate?(cb: ((dt: number) => void) | null): void
|
|
252
|
+
/** The engine's clock multiplier for physics / animators / particles (1 normal, 0 frozen) — the
|
|
253
|
+
* SDK's `Time.scale` / `Time.paused` pushed down so the sims stay in step with game code. The
|
|
254
|
+
* two aspect phases still receive the RAW wall-clock dt (the SDK scales it itself). Optional:
|
|
255
|
+
* a host without it keeps its sims at wall-clock speed. */
|
|
256
|
+
setTimeScale?(scale: number): void
|
|
257
|
+
// Physics contact/sensor events (drained after each step): a/b = entity ids, type 0 enter / 1 exit.
|
|
258
|
+
setOnPhysicsEvent(cb: (a: number, b: number, type: number) => void): void
|
|
259
|
+
|
|
260
|
+
// ---- Animation system (docs/animation-v2-plan.md): AnimationClip + Animator — THE skeletal animation
|
|
261
|
+
// path, evaluated by creator-anim on every host. A clip set is parsed straight from GLB bytes (tracks
|
|
262
|
+
// target bone NAMES, no entities); a model's embedded clips are registered by createGlb (getGlbClipSet,
|
|
263
|
+
// 0 = none). An Animator binds clips to one node hierarchy by name; the native evaluator runs the WHOLE
|
|
264
|
+
// per-frame loop (sources, transitions, blend spaces, one-shot hand-over, root motion) — the SDK only
|
|
265
|
+
// issues play/stop/blend calls and has no tick. Skinning is flushed AFTER the late phase so IK /
|
|
266
|
+
// procedural joint writes land in the skin.
|
|
267
|
+
// TRANSITIONS ARE INERTIAL, NOT CROSSFADES: a layer evaluates exactly ONE source (its one-shot, its
|
|
268
|
+
// loop, or nothing); a switch records the difference between the pose the layer SHOWED and the pose the
|
|
269
|
+
// new source shows and decays it away over `fade` seconds (halflife = 0.4 × fade). A replaced source is
|
|
270
|
+
// silent from that moment — it costs nothing, its weight is 0 at once, and it may be replaced again
|
|
271
|
+
// mid-transition (the offset is re-recorded from the displayed pose). `fade` 0 = cut.
|
|
272
|
+
loadClips(systemId: number, onComplete: (clipSetId: number) => void, onReject: (err: unknown) => void): void
|
|
273
|
+
// names = newline-joined track targets; data = [trackCount, duration (<=0 → max key time), (path 0 T/1 R/2 S,
|
|
274
|
+
// interp 0 linear/1 step/2 cubic, comps, keyCount, times…, values…)*]. Returns a one-clip set id (0 = bad).
|
|
275
|
+
createClipFromTracks(names: string, data: Float32Array): number
|
|
276
|
+
getClipSetInfo(clipSetId: number): { name: string, duration: number, trackCount: number }[]
|
|
277
|
+
// A clip DERIVED from one of the set as a NEW single-clip set (index 0) — AnimationClip.from(clip, { mirror,
|
|
278
|
+
// from, to }): the mirror (left ↔ right on the set's own rig, the GLB's node tree: contacts swapped, heading
|
|
279
|
+
// negated), then the [start, end] window re-timed to 0 (start < 0 = whole, end < 0 = the clip's end; boundary
|
|
280
|
+
// values interpolated in, events re-timed). 0 = bad id / range, or a mirror asked of a set without a rig.
|
|
281
|
+
deriveClip(clipSetId: number, clip: number, mirror: boolean, start: number, end: number): number
|
|
282
|
+
// Clip events on the CLIP: normalized times (sorted ascending). Every slot bound to the clip, in every
|
|
283
|
+
// animator, fires slot event type 4 + i on crossing event i. Empty = clear.
|
|
284
|
+
setClipEvents(clipSetId: number, clip: number, times: Float32Array): void
|
|
285
|
+
getGlbClipSet(entityId: number): number
|
|
286
|
+
destroyClipSet(clipSetId: number): void
|
|
287
|
+
animatorCreate(entityId: number): number // 0 = not a transform node
|
|
288
|
+
animatorDestroy(animatorId: number): void // leaves the skeleton in rest pose
|
|
289
|
+
// One (clip, layer) slot, silent until played / made a blend member. slot index or -1.
|
|
290
|
+
animatorBind(animatorId: number, clipSetId: number, clipIndex: number, layer: number): number
|
|
291
|
+
animatorBoundTracks(animatorId: number, slot: number): number
|
|
292
|
+
// The layer's LOOP: member slots + positions (dims 1: x per member, 2: x,y; one member = a plain looping
|
|
293
|
+
// clip). The members share ONE cycle clock, each placed on it LINEARLY by `phases` — two floats per member,
|
|
294
|
+
// (offset, cycles): φ(t) = offset + cycles · t / duration, 0 at a left-foot-down (measured offline
|
|
295
|
+
// from the clip's foot marks). An empty array, or cycles <= 0 for a member = normalized time (0, 1) and no
|
|
296
|
+
// cycle to phase-match to — the clock never reads the clip's marks. animatorSetBlendValue picks the mix (1D linear between neighbours /
|
|
297
|
+
// 2D gradient band). Setting it takes the layer over from whatever it shows — the previous loop and any
|
|
298
|
+
// one-shot on it go silent — with a transition of `fade`. Empty = no loop. speed = the members' rate.
|
|
299
|
+
animatorSetBlend(animatorId: number, layer: number, dims: 1 | 2, slots: Uint16Array, positions: Float32Array, fade: number, speed: number, phases: Float32Array): void
|
|
300
|
+
animatorSetBlendValue(animatorId: number, layer: number, x: number, y: number): void
|
|
301
|
+
// Play a slot as the layer's one-shot, transitioned in over fadeIn (0 = cut) from whatever the layer
|
|
302
|
+
// showed (playing a blend MEMBER brings the whole blend back instead). A non-looping one-shot hands the
|
|
303
|
+
// layer back to the loop at the end, the hand-over firing fadeOut seconds BEFORE the end and the return
|
|
304
|
+
// transition taking fadeOut; fadeOut < 0 = not given (cut back; on a loopless layer hold the last frame).
|
|
305
|
+
// restart = rewind even if already playing (a restart is a new source: it transitions from the pose shown).
|
|
306
|
+
animatorPlay(animatorId: number, slot: number, loop: boolean, speed: number, fadeIn: number, fadeOut: number, restart: boolean): void
|
|
307
|
+
// TURN WARP for the slot's current play (right after animatorPlay): the node's turn from the clip's baked heading is
|
|
308
|
+
// scaled to `radians` total; the pose keeps its own turn, the extra pivots about the planted foot. enabled false =
|
|
309
|
+
// the clip's own turn. Optional: older hosts lack it.
|
|
310
|
+
animatorSlotSetTurn?(animatorId: number, slot: number, radians: number, enabled: boolean): void
|
|
311
|
+
// Release over `fade` (a transition toward what is left — the loop, or the rest pose): one slot; a
|
|
312
|
+
// layer's one-shot + loop (slot -1); everything (layer -1).
|
|
313
|
+
animatorStop(animatorId: number, layer: number, slot: number, fade: number): void
|
|
314
|
+
animatorSeek(animatorId: number, slot: number, time: number): void // seeking a blend member moves the blend
|
|
315
|
+
animatorGetSlotTime(animatorId: number, slot: number): number
|
|
316
|
+
animatorGetSlotWeight(animatorId: number, slot: number): number // 1 = the layer's source, a loop member = its share, else 0
|
|
317
|
+
// Layer config: weight 0–1; additive = each slot's DELTA vs its clip's first frame on top of the layers
|
|
318
|
+
// below; maskRoot = bone name(s, '\n'-separated) whose subtrees the layer drives ("" = all).
|
|
319
|
+
animatorSetLayer(animatorId: number, layer: number, weight: number, additive: boolean, maskRoot: string): void
|
|
320
|
+
// ANTICIPATION for the layer's next source change: the transition starts with -amount x the new source's
|
|
321
|
+
// joint velocity (a wind-up against the coming motion), consumed by that switch. Optional: older hosts lack it.
|
|
322
|
+
animatorSetLayerAnticipation?(animatorId: number, layer: number, amount: number): void
|
|
323
|
+
animatorSetGlobal(animatorId: number, speed: number, paused: boolean): void
|
|
324
|
+
// Root motion: "" off, "*" auto (the shallowest joint a base-layer clip translates), else a bone name. The
|
|
325
|
+
// root's horizontal travel (animator-node frame) is stripped from the pose and, per apply: 0 accumulated
|
|
326
|
+
// only (animatorGetRootMotion copies + clears out[3]), 1 added to the node's transform, 2 fed to the
|
|
327
|
+
// CharacterController on the node or an ancestor as a world velocity (falls back to 1 without one).
|
|
328
|
+
/** `apply` bits 0–1: 0 accumulate only / 1 move the node / 2 feed the CharacterController; bit 2 (+4): the
|
|
329
|
+
* root joint's yaw about the node's up is root motion too (off the pose, onto the node the travel lands on). */
|
|
330
|
+
animatorSetRootMotion(animatorId: number, bone: string, apply: number): void
|
|
331
|
+
animatorGetRootMotion(animatorId: number, out: Float32Array): void
|
|
332
|
+
// Slot events: 0 completed (non-loop end) / 1 loop wrapped / 2 settled (no longer a source, after a stop
|
|
333
|
+
// or a replacement) / 3 HAND-OVER (a one-shot's return starts — for the SDK the clip is over; what the app
|
|
334
|
+
// starts in response takes the layer over instead) / 4+i clip event i. Single-slot (routed by animatorId).
|
|
335
|
+
setOnAnimatorEvent(callback: (animatorId: number, slot: number, type: number) => void): void
|
|
336
|
+
// ---- contacts, phase, root curves (docs/animation-v2-plan.md §2.5–2.6) ----
|
|
337
|
+
// Every clip bound to a skeleton is baked once against it: when each foot is planted, the gait phase
|
|
338
|
+
// φ(t) (0 at a left-foot-down, 0.5 at a right-foot-down, unwrapped over the clip; absent for a clip
|
|
339
|
+
// with no gait cycle) and the root's cumulative travel / yaw / speed. A controller asks these instead
|
|
340
|
+
// of shipping measured tables of its own.
|
|
341
|
+
// The feet: '\n'-joined bone names per side (foot[, toe/ball]); both "" = classify by name. Re-bakes.
|
|
342
|
+
animatorSetFeet(animatorId: number, left: string, right: string): void
|
|
343
|
+
// One curve of a slot's clip at `time` seconds (< 0 = the slot's clock now): which 0 φ (-1 = no gait)
|
|
344
|
+
// / 1 travel (m) / 2 yaw (rad, + = left) / 3 speed (m/s) / 4-5 unit travel direction x / z
|
|
345
|
+
// (model space, held through stills — integrate dir × d(travel) for the root's 2D path).
|
|
346
|
+
animatorSlotCurveAt(animatorId: number, slot: number, which: 0 | 1 | 2 | 3 | 4 | 5 | 6, time: number): number
|
|
347
|
+
// out ← [curve sample dt, total travel (m), mean speed (m/s), in-place flag]. False = unbound slot.
|
|
348
|
+
animatorSlotCurveInfo(animatorId: number, slot: number, out: Float32Array): boolean
|
|
349
|
+
animatorSlotTurn(animatorId: number, slot: number): number // the clip's total root yaw, rad
|
|
350
|
+
// The first time the clip has turned `yaw` radians — where a turn is entered by a body already
|
|
351
|
+
// that far into the same turn, so the two read as one move.
|
|
352
|
+
animatorSlotTimeAtTurn(animatorId: number, slot: number, yaw: number): number
|
|
353
|
+
// What the LAYER shows, as a cycle phase in [0, 1) — its loop's clock, or its one-shot's φ; -1 = none.
|
|
354
|
+
animatorLayerPhase(animatorId: number, layer: number): number
|
|
355
|
+
// Seek the slot to the first time whose φ ≡ phase (mod 1); a blend member moves its whole group.
|
|
356
|
+
animatorSeekPhase(animatorId: number, slot: number, phase: number): void
|
|
357
|
+
// How far the slot's pose is from `target`'s at the same cycle phase, metres (joint distance +
|
|
358
|
+
// the velocity difference over 0.1 s, the planted foot weighted most) — what handing over to that
|
|
359
|
+
// clip would hand the inertializer. Fills `out` at the curve rate, returns the sample count.
|
|
360
|
+
// align: 0 = compare at the same cycle phase, 1 = at the same time (two clips that both begin
|
|
361
|
+
// from standing have no shared cycle to line up on).
|
|
362
|
+
animatorSlotFit(animatorId: number, slot: number, target: number, align: 0 | 1, out: Float32Array): number
|
|
363
|
+
// The earliest time in the slot where that hand-over costs no more than `tolerance` metres;
|
|
364
|
+
// atContact snaps to the next foot-down at or after it. -1 = never that close.
|
|
365
|
+
animatorSlotExit(animatorId: number, slot: number, target: number, tolerance: number, atContact: boolean, align: 0 | 1): number
|
|
366
|
+
// CYCLE ALIGNMENT by pose, no marks: given slot a's cycle (offA, cyclesA), the (offset, cycles) of slot b
|
|
367
|
+
// under which the two loops show the same pose at the same gait phase — b's cycle count searched over
|
|
368
|
+
// cyclesA × {1/3 … 3}, its offset on a fine grid. out = [offset, cycles, score (metres), margin (runner-up
|
|
369
|
+
// ≥ 0.2 cycle away minus the best; ~0 = ambiguous)]. Returns 1, or 0 when there is nothing to compare.
|
|
370
|
+
animatorSlotAlign(animatorId: number, a: number, b: number, offA: number, cyclesA: number, out: Float32Array): number
|
|
371
|
+
// Contact spans as (side 0 left / 1 right, from, to, atX, atY, atZ) sextuplets (seconds, model space);
|
|
372
|
+
// returns the span count, filling `out` up to its capacity.
|
|
373
|
+
animatorSlotContacts(animatorId: number, slot: number, out: Float32Array): number
|
|
374
|
+
// A CLIMBING clip's tread levels (model-space plant heights, sorted ascending): out[0] = the
|
|
375
|
+
// riser (median level spacing), out[1..] = the levels, filled up to out's capacity. Returns the
|
|
376
|
+
// level count — 0 for a flat clip.
|
|
377
|
+
animatorSlotTreads(animatorId: number, slot: number, out: Float32Array): number
|
|
378
|
+
// The clip's baked physics at `time` seconds (< 0 = the slot's current time), unit body mass,
|
|
379
|
+
// model space: out11 = COM position xyz, COM velocity xyz (= linear momentum per kg), angular
|
|
380
|
+
// momentum about the COM xyz, then per-foot support left/right (contact-gated, seesaw split,
|
|
381
|
+
// scaled by the vertical force proxy — > 1 on a landing, 0 in flight). 0 = no body segments
|
|
382
|
+
// classified on this skeleton.
|
|
383
|
+
animatorSlotPhysics(animatorId: number, slot: number, time: number, out: Float32Array): number
|
|
384
|
+
// The clip's MATCHING FEATURE ROW at `time` (37 floats, the clip's heading frame at that time —
|
|
385
|
+
// x lateral (+ left), y up, z forward): 0–5 feet positions (relative to the pelvis' ground
|
|
386
|
+
// point), 6–11 feet velocities, 12–14 pelvis velocity, 15 pelvis height, 16–18 COM velocity,
|
|
387
|
+
// 19–20 support L/R, 21–22 contact phase L/R, 23 yaw angular momentum, 24–31 the clip's own
|
|
388
|
+
// path 0.3/0.6/1.0/1.5 s ahead as (lateral, forward) pairs, 32–35 facing change at those
|
|
389
|
+
// horizons (rad, + = left), 36 cyclic flag. Returns 37, or 0 without a leg chain.
|
|
390
|
+
animatorSlotFeatures(animatorId: number, slot: number, time: number, out: Float32Array): number
|
|
391
|
+
// The calibrated knee HINGE AXIS of a side (0 left / 1 right): a unit vector in the thigh's local
|
|
392
|
+
// frame — a skeleton property, measured over every bound clip's knee rotation track. out8 = axis
|
|
393
|
+
// xyz, spread mean (rad), spread max (rad), measurement count, 0, 0. 0 = no leg / no knee motion.
|
|
394
|
+
animatorKneeAxis(animatorId: number, side: number, out: Float32Array): number
|
|
395
|
+
// The knee's bend plane of a slot's clip at `time` seconds (< 0 = the slot's current time),
|
|
396
|
+
// predicted from the hinge axis + the clip's own thigh rotation — continuous even where the leg
|
|
397
|
+
// is straight. out6 = pole xyz (unit, model space, toward the knee — a two-bone solver's bend
|
|
398
|
+
// direction), then the plane normal xyz. 0 = uncalibrated / no leg.
|
|
399
|
+
animatorSlotKneePole(animatorId: number, slot: number, side: number, time: number, out: Float32Array): number
|
|
400
|
+
// Step warp v2: stride scales the feet's travel-direction offsets from the hips (uniform through
|
|
401
|
+
// stance and swing), lift = metres ADDED to their height (swing-gated by the contact marks;
|
|
402
|
+
// 0 = neutral, negative = a shuffle; half of what it adds raises the pelvis, capped by the
|
|
403
|
+
// planted legs' remaining extension), pitchDeg rotates each foot about its lateral axis
|
|
404
|
+
// (+ = toes up), slopeDeg the invisible staircase (+ = ascending: foot heights follow the
|
|
405
|
+
// incline + the feet auto-pitch; the HOST climbs the body at tan(slope) × the stride-scaled
|
|
406
|
+
// travel, which holds each planted foot's world height constant on its tread). Solved in the
|
|
407
|
+
// calibrated knee hinge plane with a soft reach; the pelvis lowers by any leg's overreach
|
|
408
|
+
// (marks-weighted, spring-followed, zero when nothing overreaches). 1/0/0/0 = identity;
|
|
409
|
+
// on false = off.
|
|
410
|
+
animatorSetStepWarp(animatorId: number, on: boolean, stride: number, lift: number, pitchDeg: number, slopeDeg: number): void
|
|
411
|
+
// Footsteps: a contact that BEGAN this evaluation on what the base layer shows — side 0 left / 1 right,
|
|
412
|
+
// x/y/z = the foot's WORLD position at the plant. Fired after the frame's transform commit.
|
|
413
|
+
setOnAnimatorStep(callback: (animatorId: number, side: number, x: number, y: number, z: number) => void): void
|
|
414
|
+
|
|
415
|
+
// ---- drives + warping ----
|
|
416
|
+
// The character's world velocity this frame: the speed the stride warp fits the stride to and the
|
|
417
|
+
// direction the orientation warp turns the lower body toward.
|
|
418
|
+
animatorSetMotion(animatorId: number, vx: number, vy: number, vz: number): void
|
|
419
|
+
// Cumulative capsule travel (m) and yaw (rad, + = left) — what a slot's distance / angle drive reads.
|
|
420
|
+
animatorSetDriveInput(animatorId: number, distance: number, angle: number): void
|
|
421
|
+
// Drive a slot's clock by a quantity instead of time: 0 time / 1 distance / 2 angle. `entry` is the
|
|
422
|
+
// curve value that corresponds to NOW (a start 0; a stop with D metres left: total travel − D), so
|
|
423
|
+
// the clip is entered where it already agrees with the body. Stalls fall back to time.
|
|
424
|
+
animatorSetSlotDrive(animatorId: number, slot: number, mode: 0 | 1 | 2, entry: number): void
|
|
425
|
+
// [stride on, stride min, stride max, orient on, orient max°, orient time, min speed, pelvis drop]
|
|
426
|
+
animatorSetWarpParams(animatorId: number, params: Float32Array): void
|
|
427
|
+
|
|
428
|
+
// ---- feet: foot lock + ground IK (docs/animation-v2-plan.md §2.9) ----
|
|
429
|
+
// The feet stage runs in WORLD space inside the evaluation, after the clips are composited: a foot
|
|
430
|
+
// the shown clip calls planted is pinned where it landed and the leg re-solved to keep it there
|
|
431
|
+
// while the body moves on (the lock), and each foot is put on the ground the ENGINE probed under it,
|
|
432
|
+
// the pelvis lowered so the leg reaches (ground IK). The engine casts the probe rays itself against
|
|
433
|
+
// what a character can stand on (static + moving solids; never the character's own bodies, debris
|
|
434
|
+
// or sensors) and reads the CharacterController's ground state — nothing per frame from the SDK.
|
|
435
|
+
// [ik on, lock on, pelvis drop m, unlock distance m, lock-in s, lock-out s, pelvis spring s,
|
|
436
|
+
// align to ground normal 0..1, probe half-length m, detector max speed m/s, detector max height m]
|
|
437
|
+
// Optional: a host without it has no feet stage (the legs stay as animated).
|
|
438
|
+
animatorSetFeetParams?(animatorId: number, params: Float32Array): void
|
|
439
|
+
// One foot after this frame's evaluation, side 0 left / 1 right: out ← [locked, lock weight,
|
|
440
|
+
// anchor xyz, target xyz] (world) — a debug overlay's beam under the foot. False = no such foot.
|
|
441
|
+
animatorFootState?(animatorId: number, side: number, out: Float32Array): boolean
|
|
442
|
+
|
|
443
|
+
// ---- locomotion: the movement model + the clip selector, both engine-side ----
|
|
444
|
+
// The intent (`locoSetInput`) becomes a desired velocity; the simulated velocity springs toward it
|
|
445
|
+
// one fixed substep at a time (`locoStep`, given the capsule's place), and `locoUpdate` — called
|
|
446
|
+
// before the animators are evaluated — picks and drives what the base layer shows. The host moves
|
|
447
|
+
// the character with the velocity and facing it reads back: in displacement `code` the animation
|
|
448
|
+
// never moves the body, so "how fast am I" is an input to the animation, not an output of it.
|
|
449
|
+
locoCreate(animatorId: number): number
|
|
450
|
+
locoDestroy(loco: number): void
|
|
451
|
+
// [halflife walk, halflife run, halflife facing, speed walk, speed run, speed sprint, deadzone,
|
|
452
|
+
// turn min°, turn big°, blend, stop blend, start tap, resume, predict, displacement (0 code /
|
|
453
|
+
// 1 data / 2 hybrid), mode (0 rules / 1 matching), match interval, match blend, spin min°, turn
|
|
454
|
+
// rate cap (deg/s, 0 = uncapped), halflife braking, hybrid adjustment clamp (m/s)]
|
|
455
|
+
locoSetParams(loco: number, params: Float32Array): void
|
|
456
|
+
locoDefaults(out: Float32Array): void
|
|
457
|
+
// Register a bound slot: kind 0 idle / 1 gait / 2 start / 3 stop / 4 turn / 5 match / 6 spin
|
|
458
|
+
// (a turn on the spot); `angle` degrees (+ = left) for the starts / turns / spins, `speed` m/s for
|
|
459
|
+
// a gait (0 = the clip's own measured speed), `gait` the gait a transition belongs to (0 walk /
|
|
460
|
+
// 1 run / 2 sprint, -1 = any) — a walking body plays the walking starts, stops and turns.
|
|
461
|
+
locoSetEntry(loco: number, slot: number, kind: number, angle: number, speed: number, gait: number): void
|
|
462
|
+
locoClearSet(loco: number): void
|
|
463
|
+
// [dir x, dir z, magnitude 0–1, face x, face z, gait 0 walk / 1 run / 2 sprint] — the facing is
|
|
464
|
+
// independent of the movement: a released key with a heading still owed turns the body on the spot.
|
|
465
|
+
locoSetInput(loco: number, input: Float32Array): void
|
|
466
|
+
// One simulation step at the capsule's world place — from the fixed substep loop.
|
|
467
|
+
locoStep(loco: number, dt: number, px: number, py: number, pz: number): void
|
|
468
|
+
// Run the selector for this frame — before the animators are evaluated.
|
|
469
|
+
locoUpdate(loco: number, dt: number): void
|
|
470
|
+
// out ← [state (0 idle / 1 start / 2 move / 3 turn / 4 stop / 5 spin), speed, vel x/y/z, yaw (rad,
|
|
471
|
+
// 0 = +Z, + = toward +X), yaw rate, phase, state sequence, then 3 × (x, z, dir x, dir z) predicted
|
|
472
|
+
// at +0.2 / +0.4 / +0.7 s].
|
|
473
|
+
locoRead(loco: number, out: Float32Array): void
|
|
474
|
+
// Why the last STOP was the one played: one row of 9 floats per candidate weighed — [slot, entry
|
|
475
|
+
// time, metres it still travels, metres the body needs, seconds to its next foot-down, foot-downs
|
|
476
|
+
// left, flags (1 = its phase matched, 2 = at/after its first foot-down, 4 = played, 8 = entered
|
|
477
|
+
// ahead of that foot-down by its pose), score, pose distance from what showed (m, -1 = not
|
|
478
|
+
// measured)]. Returns the rows written. A debug read; absent on hosts predating it.
|
|
479
|
+
locoStopReport?(loco: number, out: Float32Array): number
|
|
480
|
+
// Build the motion-matching database over the registered set (selector mode 1); returns frames.
|
|
481
|
+
locoBuildDatabase(loco: number): number
|
|
482
|
+
|
|
483
|
+
/** Subtree AABB in the entity's OWN local space (its own transform excluded) as
|
|
484
|
+
* [minX,minY,minZ, maxX,maxY,maxZ] — zeros for an empty / not-yet-loaded subtree. What
|
|
485
|
+
* `Shape.fit()` measures. Optional: absent on hosts predating the binding. */
|
|
486
|
+
computeBoundingBox?(entityId: number): Float32Array
|
|
487
|
+
setColliderFromMesh(entityId: number, meshEntityId: number, form: number): void
|
|
488
|
+
setColliderBox(entityId: number, centerX: number, centerY: number, centerZ: number, sizeX: number, sizeY: number, sizeZ: number): void
|
|
489
|
+
setColliderSphere(entityId: number, centerX: number, centerY: number, centerZ: number, radius: number): void
|
|
490
|
+
|
|
491
|
+
// JoltPhysics. motionType: 0 static / 1 kinematic / 2 dynamic.
|
|
492
|
+
physicsHasSupport(): boolean
|
|
493
|
+
/** Lightmap bake (docs/lightmap-plan.md) — a dev-time tool compiled into the desktop host only;
|
|
494
|
+
* `lightmapBake` exists only where `lightmapHasSupport()` is true. Writes the raster (lightmap.png, an intermediate the CLI turns into lightmap.ktx2)
|
|
495
|
+
* — one per atlas PAGE (`lightmap_<n>.png`, up to `maxPages` of `size` before the texel coarsens) —, the point lights' baked
|
|
496
|
+
* irradiance (`lightmap-light[_<n>].png`, sRGB(E / lightScale), `lightRays` shadow rays toward a `lightRadius`-metre disc) when the
|
|
497
|
+
* scene holds point lights, lightmap.bake (rects, pages, the baked lights) and lightmap.volume (`volumeCell` > 0)
|
|
498
|
+
* into outDir (R = sun visibility, G = ambient occlusion) for the given static instances (GLB roots /
|
|
499
|
+
* Mesh entities; `keysJoined` = one key per id, '
|
|
500
|
+
'-joined). Synchronous; progress on stdout. */
|
|
501
|
+
lightmapHasSupport?(): boolean
|
|
502
|
+
/** Lightmap consumption (docs/lightmap-plan.md §3): the next createGlb takes lightmap.filamat (the material
|
|
503
|
+
* behind that instance id) instead of the ubershader and keeps TEXCOORD_1; UINT32_MAX clears. */
|
|
504
|
+
setNextGlbLightmapped?(materialInstanceId: number): void
|
|
505
|
+
/** The level-wide knobs every lightmap-material instance shares (applied to the ones that exist and to every one
|
|
506
|
+
* created afterwards): the sun-mask shadow math (ambientScale, sunStrength), how much baked AO applies (aoStrength,
|
|
507
|
+
* 1 = all) and the light atlas' / volume's physical irradiance per encoded 1.0 (lightScale; 0 = no baked lights).
|
|
508
|
+
* volumeLightScale = the light VOLUME's own scale (movers); omitted or < 0 = same as lightScale. lightGamma = the light
|
|
509
|
+
* store's curve, texel = sRGB(pow(E / lightScale, 1 / lightGamma)) — 1 (default) for the linear v2 store, 2 for the
|
|
510
|
+
* square-root store bakes write since 2026-08-31 (the .bake's `lightGamma`). */
|
|
511
|
+
lightmapSetOptions?(ambientScale: number, sunStrength: number, aoStrength: number, lightScale: number, volumeLightScale?: number, lightGamma?: number): void
|
|
512
|
+
/** Bind the atlas page + this instance's rect (uv1 * [sx, sy] + [ox, oy]) and, unless 0xFFFFFFFF, the matching page of
|
|
513
|
+
* the light atlas; the sun / IBL terms come from filament's per-frame uniforms inside the shader. Returns how many
|
|
514
|
+
* material instances took it (0 = not loaded lightmapped). */
|
|
515
|
+
lightmapApply?(entityId: number, textureId: number, sx: number, sy: number, ox: number, oy: number, lightTextureId: number): number
|
|
516
|
+
/** Shadow flags on every renderable of a GLB instance (Mesh has setCastShadows/setReceiveShadows). */
|
|
517
|
+
setGlbShadows?(entityId: number, cast: boolean, receive: boolean): void
|
|
518
|
+
lightmapBake?(outDir: string, entityIds: Uint32Array, keysJoined: string, size: number, texel: number, sunRays: number, aoRays: number, aoDistance: number, bias: number, sunAngleDeg: number, volumeCell: number, maxPages: number, lightRays: number, lightRadius: number, bounceAlbedo?: number, bounceDistance?: number, bounceRays?: number, coplanarSkip?: number, denoise?: number): boolean
|
|
519
|
+
/** Light VOLUME for dynamic objects (docs/lightmap-plan.md §9). `lightmapVolumeLoad` turns a fetched
|
|
520
|
+
* lightmap.volume (`fetchSystemId` from `_creatorUtils.fetch`) into RGBA8 3D textures and returns its
|
|
521
|
+
* header as JSON — `{"texture":id,"dims":[nx,ny,nz],"min":[x,y,z],"cell":m,"light"?:id,"faces"?:n}` (`light` = the
|
|
522
|
+
* point lights' block: a version-3 volume's six ambient-cube faces (+X −X +Y −Y +Z −Z, `faces` 6), a version-2
|
|
523
|
+
* volume's one directionless value (`faces` 1) — uploaded either way as six face slabs stacked along z, so the
|
|
524
|
+
* light texture's depth is nz × 6) — or "" on failure. */
|
|
525
|
+
lightmapVolumeLoad?(fetchSystemId: number): string
|
|
526
|
+
/** Make those textures THE volume (`textureId` 0xFFFFFFFF clears; `lightTextureId` 0xFFFFFFFF = no baked lights):
|
|
527
|
+
* every lightmap-material instance without an atlas rect — loaded already or later — samples it at the pixel's
|
|
528
|
+
* world position (+ half a `cell` along the normal). `size` = dims × cell. Returns how many instances switched. */
|
|
529
|
+
lightmapVolumeSet?(textureId: number, lightTextureId: number, minX: number, minY: number, minZ: number, sizeX: number, sizeY: number, sizeZ: number, cell: number): number
|
|
530
|
+
physicsConfigure(gx: number, gy: number, gz: number, maxBodies: number): void
|
|
531
|
+
setInterpolation(enabled: boolean): void
|
|
532
|
+
// Shape/Physics/Trigger aspects: build a shape once, create bodies from it.
|
|
533
|
+
physicsBuildBox(hx: number, hy: number, hz: number): number
|
|
534
|
+
physicsBuildSphere(radius: number): number
|
|
535
|
+
physicsBuildCylinder(halfHeight: number, radius: number): number
|
|
536
|
+
physicsBuildCapsule(halfHeight: number, radius: number): number
|
|
537
|
+
/** Mesh shape from node-local triangles. convex=false → triangle mesh (static/kinematic/pick/character
|
|
538
|
+
* only; physicsCreateBody returns 0 for a dynamic one), convex=true → convex hull (any motion).
|
|
539
|
+
* (sx,sy,sz) = world scale, applied natively. Returns 0 if the shape can't be built. */
|
|
540
|
+
physicsBuildMesh(vertices: Float32Array, indices: Uint32Array, convex: boolean, sx: number, sy: number, sz: number): number
|
|
541
|
+
/** Same from a loaded GLB root (non-skinned primitives, bind pose, baked sub-node transforms; cached per asset). */
|
|
542
|
+
physicsBuildMeshFromEntity(entityId: number, convex: boolean, sx: number, sy: number, sz: number): number
|
|
543
|
+
/** Terrain collider (Shape { heightfield: true }, docs/terrain-plan.md §1.4): a Jolt HeightFieldShape over
|
|
544
|
+
* the grid `terrainCreate` draws (same arrays, same hole rule). Static / kinematic / pick / character
|
|
545
|
+
* ground only. (sx,sy,sz) = world scale. `physicsUpdateHeightField` rewrites a sample rectangle in
|
|
546
|
+
* place from the FULL arrays (live bodies keep the shape); heights beyond the range chosen at build
|
|
547
|
+
* time (25 % headroom) clamp — the SDK rebuilds the shape when an edit leaves that range. Optional. */
|
|
548
|
+
physicsBuildHeightField?(heights: Float32Array, sizeX: number, sizeZ: number, cellSize: number, holes: Uint8Array | null, sx: number, sy: number, sz: number): number
|
|
549
|
+
physicsUpdateHeightField?(shapeId: number, heights: Float32Array, sizeX: number, sizeZ: number, x0: number, z0: number, w: number, h: number, holes: Uint8Array | null): void
|
|
550
|
+
/** A loaded GLB root's triangle soup — the one `physicsBuildMeshFromEntity` collides — as 9 floats per
|
|
551
|
+
* triangle in the asset root's space (empty when the entity is not a GLB). `Terrain.conform` stamps a
|
|
552
|
+
* road model into the ground with it. Optional. */
|
|
553
|
+
glbTriangles?(entityId: number): Float32Array
|
|
554
|
+
/** Offset a built shape's centre from the node's origin (Shape `origin`) — world units in the
|
|
555
|
+
* body's rotated, UNSCALED frame, sitting outside a mesh shape's scale wrapper. Sets rather
|
|
556
|
+
* than accumulates; (0,0,0) clears it. Optional: an older host just centres on the node. */
|
|
557
|
+
physicsSetShapeOrigin?(shapeId: number, x: number, y: number, z: number): void
|
|
558
|
+
/** Swap a live body's shape, keeping its id, velocity and transform (Shape.fit / a re-attach).
|
|
559
|
+
* updateMass recomputes the inertia tensor. Refuses a triangle mesh on a dynamic body. */
|
|
560
|
+
physicsSetBodyShape?(bodyId: number, shapeId: number, updateMass: boolean): void
|
|
561
|
+
physicsDestroyShape(shapeId: number): void
|
|
562
|
+
/** sensor = trigger (overlap events, no response); pickOnly = raycast-only, non-colliding body. */
|
|
563
|
+
physicsCreateBody(entityId: number, shapeId: number, motion: number, mass: number, sensor: boolean, pickOnly: boolean): number
|
|
564
|
+
physicsSetPickable(bodyId: number, pickable: boolean): void
|
|
565
|
+
/** Surface friction of one body (0 = ice, ~1 = grippy asphalt). Values COMBINE as sqrt(a * b), so
|
|
566
|
+
* a low value on either side dominates. New bodies start at 0.6 — a neutral solid surface.
|
|
567
|
+
* The vehicle wheel cast reads the GROUND body's value — this is what caps a car's cornering. */
|
|
568
|
+
physicsSetFriction(bodyId: number, friction: number): void
|
|
569
|
+
physicsGetFriction(bodyId: number): number
|
|
570
|
+
/** Ray vs pickable bodies → hit entity id (0 = miss); fills `out` = [px,py,pz,nx,ny,nz,fraction]. */
|
|
571
|
+
physicsRaycast(ox: number, oy: number, oz: number, dx: number, dy: number, dz: number, maxDist: number, out?: Float32Array): number
|
|
572
|
+
/** Dev-time dump of the static collision geometry (docs/navmesh-plan.md §4) — the input of
|
|
573
|
+
* `lecodes navmesh bake`: every STATIC solid body's triangles in world space, as an NGEO file at
|
|
574
|
+
* `outPath`. `entityIds`/`areas` are per-entity overrides (area 0..15, 255 unwalkable, 254 skip).
|
|
575
|
+
* Returns the triangle count (-1 = failed). Desktop hosts with physics only. */
|
|
576
|
+
physicsStaticGeometry?(outPath: string, entityIds: Uint32Array, areas: Uint8Array): number
|
|
577
|
+
// CharacterController (Jolt CharacterVirtual). The character steps on the engine's FIXED clock like
|
|
578
|
+
// every body (frame-rate independent) and is render-interpolated; the engine owns its gravity, so
|
|
579
|
+
// the SDK never ticks it. Both velocity halves are LATCHED STATE, never one-shot events — JS runs
|
|
580
|
+
// once per frame while the sim runs 0..4 sub-steps, so a one-shot would double-apply or vanish.
|
|
581
|
+
// groundState: 0 OnGround / 1 OnSteepGround / 2 NotSupported / 3 InAir.
|
|
582
|
+
characterCreate(entityId: number, shapeId: number, maxSlopeDeg: number): number
|
|
583
|
+
characterDestroy(charId: number): void
|
|
584
|
+
/** This frame's HORIZONTAL command (world units/s), cleared once a step consumes it — no command
|
|
585
|
+
* means standing still, not coasting. Held across the frame's sub-steps, and it takes the axis
|
|
586
|
+
* back from a latched velocity: the last writer owns X/Z. */
|
|
587
|
+
characterMove(charId: number, x: number, z: number): void
|
|
588
|
+
/** The same command including the vertical — free mode (gravityScale 0): swimming / flying. */
|
|
589
|
+
characterMoveFree(charId: number, x: number, y: number, z: number): void
|
|
590
|
+
/** Seed the LATCHED ballistic vertical (jump / dash). No ground check. */
|
|
591
|
+
characterSetVerticalVelocity(charId: number, vy: number): void
|
|
592
|
+
/** Latch the whole velocity — it persists until a characterMove takes the axis back (knockback,
|
|
593
|
+
* wall jump, launch pad, weightless flight). Gravity still acts on the vertical. */
|
|
594
|
+
characterSetVelocity(charId: number, x: number, y: number, z: number): void
|
|
595
|
+
/** Multiplier over the world gravity; 0 = free mode, which ALSO disables stick-to-floor + stairs. */
|
|
596
|
+
characterSetGravityScale(charId: number, scale: number): void
|
|
597
|
+
characterSetMaxSlope(charId: number, maxSlopeDeg: number): void
|
|
598
|
+
/** Swap the collider live (crouch / stand up), keeping the FEET planted. Returns false when the new
|
|
599
|
+
* shape doesn't fit where the character stands — nothing changed, so the caller retries later and
|
|
600
|
+
* that retry is an exact headroom test. Optional: a host without it can't resize a character. */
|
|
601
|
+
characterSetShape?(charId: number, shapeId: number): boolean
|
|
602
|
+
/** The velocity the solver ENDED UP with after the last step (post-collision), not the command. */
|
|
603
|
+
characterGetVelocity(charId: number, out: Float32Array): void
|
|
604
|
+
characterGetGroundState(charId: number): number
|
|
605
|
+
/** Discontinuous move (spawn / respawn / teleport) — also resets the interpolation pair. */
|
|
606
|
+
characterSetPosition(charId: number, x: number, y: number, z: number): void
|
|
607
|
+
// Vehicle (Jolt VehicleConstraint + WheeledVehicleController). One settings BLOB, so tuning knobs
|
|
608
|
+
// never grow this ABI — layout (floats):
|
|
609
|
+
// header[21]: version(5), mass, comAuto, comY,
|
|
610
|
+
// engTorque, engMaxRpm, engIdleRpm, engInertia, engBraking, clutchStrength,
|
|
611
|
+
// diffRatio (<= 0 = a fully OPEN differential),
|
|
612
|
+
// antiRoll (the bar's stiffness as a FRACTION of the wheel spring; 0 = no bars),
|
|
613
|
+
// maxTiltDeg,
|
|
614
|
+
// steerLockDeg, steerAtSpeedDeg, steerSpeedMs, steerRateDeg (speed-sensitive
|
|
615
|
+
// steering: the lock falls to steerAtSpeedDeg by steerSpeedMs and the wheels turn
|
|
616
|
+
// no faster than steerRateDeg per second; 0/0/0 = the raw lock, instantly),
|
|
617
|
+
// aeroDownforce, aeroDrag (each a fraction of the car's own WEIGHT at 30 m/s, scaled
|
|
618
|
+
// by v² from there; 0/0 = no aero, Jolt's own behaviour),
|
|
619
|
+
// wheelCount, curveCount
|
|
620
|
+
// + curveCount * 2: the engine's normalized torque curve (x = rpm/maxRpm, y = torque/maxTorque);
|
|
621
|
+
// 0 points keeps Jolt's default
|
|
622
|
+
// + wheelCount * 15: px, py, pz, radius, width, maxSteerDeg, drive, brakeTorque, handBrakeTorque,
|
|
623
|
+
// axle, travel, stiffness, damping, grip, tireCurve (0 = road, 1 = arcade)
|
|
624
|
+
// NO gear list and no wheel node ids: the gearbox is the SDK's (see vehicleSetTransmission) and the
|
|
625
|
+
// SDK poses the wheel nodes itself. Chassis space is forward -Z / up +Y (matching node.forward);
|
|
626
|
+
// wheel positions are suspension attachment points in unscaled chassis space; `axle` pairs wheels
|
|
627
|
+
// for the differentials + anti-roll bars.
|
|
628
|
+
vehicleCreate(entityId: number, shapeId: number, settings: Float32Array): number
|
|
629
|
+
vehicleDestroy(vehicleId: number): void
|
|
630
|
+
/** forward/right in [-1,1], brake/handBrake in [0,1]. Sticky; any non-zero input wakes the car. */
|
|
631
|
+
vehicleSetInput(vehicleId: number, forward: number, right: number, brake: number, handBrake: number): void
|
|
632
|
+
/** The SDK's gearbox, latched and applied once per fixed step: `ratio` is the ONE ratio the car is
|
|
633
|
+
* running (0 = neutral, negative = reverse — the engine never sees a gear list) and `clutch` is
|
|
634
|
+
* the 0..1 shift envelope scaling the clutch in the coupled engine/wheel solve. */
|
|
635
|
+
vehicleSetTransmission(vehicleId: number, ratio: number, clutch: number): void
|
|
636
|
+
/** Re-apply the TUNABLE half of the blob (same layout) to a live car — differential, per-wheel grip,
|
|
637
|
+
* engine torque/RPM/curve, clutch strength, steering lock/taper/rate, brake torques, tilt limit.
|
|
638
|
+
* Structural values (mass, centre of mass, wheel geometry, driven wheels, suspension, anti-roll)
|
|
639
|
+
* are ignored: those need a re-create. */
|
|
640
|
+
vehicleSetTuning?(vehicleId: number, settings: Float32Array): void
|
|
641
|
+
/** out = [speed, rpm, wheelsInContact, vx, vy, vz] + per wheel
|
|
642
|
+
* [contact, slipLong, slipAngleDeg, suspensionLength, steerDeg, spin]. The last three per wheel are
|
|
643
|
+
* its VISUAL POSE — the SDK's Wheel aspect builds the node transform from them. */
|
|
644
|
+
vehicleGetState(vehicleId: number, out: Float32Array): void
|
|
645
|
+
/** Teleport upright and clear all motion (velocities, engine RPM, gear, wheel spin). */
|
|
646
|
+
vehicleReset(vehicleId: number, x: number, y: number, z: number, qx: number, qy: number, qz: number, qw: number): void
|
|
647
|
+
/** The chassis rigid body, for the plain body calls (physicsApplyImpulse, …). 0 if unknown. */
|
|
648
|
+
vehicleBodyId(vehicleId: number): number
|
|
649
|
+
// Ragdoll (Jolt Ragdoll): a Model's skeleton handed to physics — one dynamic body per listed bone
|
|
650
|
+
// (a capsule from the bone's origin to the next joint) joined to its parent part by a swing-twist
|
|
651
|
+
// constraint. Built ONCE from the pose the bones are in (that pose is the joints' neutral for the
|
|
652
|
+
// limits) and kept out of the world until ragdollActivate, which takes the bones' CURRENT pose,
|
|
653
|
+
// adds the bodies and gives every body one velocity; from then on the engine writes the bodies'
|
|
654
|
+
// poses onto the bone entities every frame AFTER the animator (bones not listed keep their
|
|
655
|
+
// animated local pose under the ragdolled parents — fingers, toes, a spine bone between two
|
|
656
|
+
// parts), until ragdollDeactivate. Every body carries its bone entity as user data, so
|
|
657
|
+
// physicsRaycast / contact events name the bone. Optional: a host without it has no ragdolls.
|
|
658
|
+
// bones[partCount * 2]: bone entity, `to` entity (0 = a leaf: `length` along the parent's line;
|
|
659
|
+
// a leaf ROOT points along the model's up)
|
|
660
|
+
// settings — header[12]: version(2), partCount, stride(12), friction, linearDamping,
|
|
661
|
+
// angularDamping (0 = Jolt's own), collide (0 = everything, 1 = the STATIC world and
|
|
662
|
+
// other such ragdolls only: dynamic bodies, character controllers and vehicles pass
|
|
663
|
+
// through — Jolt's DEBRIS object/broadphase layer), freeze (1 = once every part is
|
|
664
|
+
// asleep the bodies turn STATIC where they lie: the last pose keeps being written
|
|
665
|
+
// onto the bones, raycasts still hit, nothing wakes them, the solver skips them;
|
|
666
|
+
// ragdollActive reads false, ragdollDeactivate / ragdollActivate still work —
|
|
667
|
+
// activate makes the parts dynamic again), freezeAfter (seconds in the world after which the freeze happens
|
|
668
|
+
// regardless; 0 = no cap), reserved x3. A version-1 blob (header[8], stops after
|
|
669
|
+
// angularDamping) is still accepted = collide everything, never freeze.
|
|
670
|
+
// + partCount * 12: parentIndex (-1 = the root; always < the part's own index), radius, length
|
|
671
|
+
// (0 = up to the `to` bone), mass (kg; 0 = from the volume), swingDeg (cone
|
|
672
|
+
// half-angle), twistDeg (half-angle), hinge (0/1), hingeAxisX/Y/Z (in the MODEL
|
|
673
|
+
// node's space), hingeMinDeg, hingeMaxDeg — a hinge is a swing-twist whose cone is
|
|
674
|
+
// flat (2°) across the axis and [min, max] about it (a knee, an elbow)
|
|
675
|
+
ragdollCreate?(rootEntityId: number, bones: Uint32Array, settings: Float32Array): number
|
|
676
|
+
ragdollDestroy?(ragdollId: number): void
|
|
677
|
+
/** Pose the bodies from the bones' current transforms, add them to the world, set every body's
|
|
678
|
+
* linear velocity. Already active = re-wake + velocity. false = unknown id / no world. */
|
|
679
|
+
ragdollActivate?(ragdollId: number, vx: number, vy: number, vz: number): boolean
|
|
680
|
+
/** Take the bodies out of the world; the animator owns the bones again from the next frame. */
|
|
681
|
+
ragdollDeactivate?(ragdollId: number): void
|
|
682
|
+
/** In the world AND at least one body still awake (a settled ragdoll reads false). */
|
|
683
|
+
ragdollActive?(ragdollId: number): boolean
|
|
684
|
+
/** The rigid body of part `index` (for physicsApplyImpulseAt / velocities). 0 if unknown. */
|
|
685
|
+
ragdollBodyId?(ragdollId: number, index: number): number
|
|
686
|
+
// Legacy coupled shape+body (still used by the worker RigidBody).
|
|
687
|
+
physicsCreateBox(entityId: number, hx: number, hy: number, hz: number, motionType: number, mass: number): number
|
|
688
|
+
physicsCreateSphere(entityId: number, radius: number, motionType: number, mass: number): number
|
|
689
|
+
physicsCreateCylinder(entityId: number, halfHeight: number, radius: number, motionType: number, mass: number): number
|
|
690
|
+
physicsSetLinearVelocity(bodyId: number, x: number, y: number, z: number): void
|
|
691
|
+
physicsGetLinearVelocity(bodyId: number, out: Float32Array): void
|
|
692
|
+
/** Angular velocity about each world axis, RADIANS/second — Jolt's unit; the SDK exposes degrees.
|
|
693
|
+
* The only way to stop a spin: a position write leaves both velocities untouched. */
|
|
694
|
+
physicsSetAngularVelocity?(bodyId: number, x: number, y: number, z: number): void
|
|
695
|
+
physicsGetAngularVelocity?(bodyId: number, out: Float32Array): void
|
|
696
|
+
physicsApplyImpulse(bodyId: number, x: number, y: number, z: number): void
|
|
697
|
+
physicsApplyImpulseAt?(bodyId: number, x: number, y: number, z: number, px: number, py: number, pz: number): void
|
|
698
|
+
physicsSetBodyPosition(bodyId: number, x: number, y: number, z: number): void
|
|
699
|
+
/** The rotation twin (normalized host-side). Both snap the body's render-interpolation pair, so a
|
|
700
|
+
* discontinuous move is drawn as one rather than as a one-frame slide/spin across the gap. */
|
|
701
|
+
physicsSetBodyRotation?(bodyId: number, qx: number, qy: number, qz: number, qw: number): void
|
|
702
|
+
physicsRemoveBody(bodyId: number): void
|
|
703
|
+
|
|
704
|
+
createMediaPlayerTexture(id: number): number
|
|
705
|
+
|
|
706
|
+
getName(entityId: number): string
|
|
707
|
+
setName(entityId: number, name: string): void
|
|
708
|
+
|
|
709
|
+
hasMesh(entityId: number): boolean
|
|
710
|
+
|
|
711
|
+
createARController(sceneId: number, cameraId: number, mode: string, onTrack: (entityId: number, track: boolean) => void): void
|
|
712
|
+
createRootAnchor(sceneId: number): number
|
|
713
|
+
createAnchor(sceneId: number, physicalWidth: number, systemId: number): number
|
|
714
|
+
|
|
715
|
+
// Particles. All emitter/curve config crosses as ONE Float32Array of [tag, payloadLen,
|
|
716
|
+
// ...payload] records, parsed once in creator-particles (CPART_TAG_* in creator-particles.h; the
|
|
717
|
+
// SDK mirror is in gl/Particles.ts, guarded by sdk/tests/particles-tags.test.ts). Unknown
|
|
718
|
+
// tags skip by length. maxParticles 0 = default (1000).
|
|
719
|
+
createParticleSystem(entityId: number, materialInstanceId: number, maxParticles: number): void
|
|
720
|
+
spawnParticles(entityId: number, count: number): void
|
|
721
|
+
setParticleSystemConfig(entityId: number, data: Float32Array): void
|
|
722
|
+
|
|
723
|
+
// Projected decals (creator-gl src/decals.h; SDK gl/DecalSet.ts). A set on an entity = one
|
|
724
|
+
// renderable of `capacity` (0 = 256) unit boxes drawn with the material instance (decal.filamat)
|
|
725
|
+
// — each box projects its atlas cell onto the opaque scene behind it through the scene depth
|
|
726
|
+
// buffer. A record is 23 floats in the SET entity's space: X Y Z axes scaled by the box's
|
|
727
|
+
// width / height / depth (Z = out of the surface), centre, atlas rect u0 v0 u1 v1, tint rgba,
|
|
728
|
+
// life (s, 0 = forever), fadeIn (s), fadeOut (s). addDecal returns the slot (0xFFFFFFFF = no
|
|
729
|
+
// set; a full set recycles its oldest); updateDecal keeps the slot's birth time. Optional:
|
|
730
|
+
// a host without them draws no decals (the SDK warns once).
|
|
731
|
+
createDecalSet?(entityId: number, materialInstanceId: number, capacity: number): void
|
|
732
|
+
addDecal?(entityId: number, record: Float32Array): number
|
|
733
|
+
updateDecal?(entityId: number, slot: number, record: Float32Array): void
|
|
734
|
+
removeDecal?(entityId: number, slot: number): void
|
|
735
|
+
clearDecals?(entityId: number): void
|
|
736
|
+
decalCount?(entityId: number): number
|
|
737
|
+
|
|
738
|
+
createNoise(): number
|
|
739
|
+
setNoiseFrequency(noiseId: number, frequency: number): void
|
|
740
|
+
setNoiseOctaves(noiseId: number, octaves: number): void
|
|
741
|
+
setNoiseFractalLunacrity(noiseId: number, lunacrity: number): void
|
|
742
|
+
setNoiseFractalGain(noiseId: number, fractalGain: number): void
|
|
743
|
+
getNoise2D(noiseId: number, x: number, y: number): number
|
|
744
|
+
getNoise3D(noiseId: number, x: number, y: number, z: number): number
|
|
745
|
+
|
|
746
|
+
captureImage(sceneId: number, onComplete: (bufferId: number, name: string, size: number) => void, onReject: () => void): void
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// ---- 2D engine (sokol / creator-2d) ----------------------------------------------------------
|
|
750
|
+
// A 2D-only project loads ONLY creator2d.wasm — never Filament.
|
|
751
|
+
var _creator2d: {
|
|
752
|
+
backend: string
|
|
753
|
+
version(): number
|
|
754
|
+
render(nowMs: number): void
|
|
755
|
+
onUpdate(cb: (dt: number) => void): void
|
|
756
|
+
offUpdate(cb: (dt: number) => void): void
|
|
757
|
+
// Render-synced aspect update(dt) dispatch, called from inside c2dRender. Early = before the
|
|
758
|
+
// physics step; late = after animations, just before draw. Single-slot per phase (the SDK's
|
|
759
|
+
// Aspect dispatcher registers one callback that iterates its ordered updater list).
|
|
760
|
+
setEarlyUpdate(cb: (dt: number) => void): void
|
|
761
|
+
setLateUpdate(cb: (dt: number) => void): void
|
|
762
|
+
/** Clock multiplier for the 2D physics step + sprite animations (see `_creator.setTimeScale`). */
|
|
763
|
+
setTimeScale?(scale: number): void
|
|
764
|
+
setOnAnimEvent(cb: (ev: { entityId: number, clipId: number, type: number }) => void): void
|
|
765
|
+
// Raw scene pointer events from the host (canvas / iOS view). phase: 0 down, 1 move, 2 up, 3 cancel;
|
|
766
|
+
// x,y in logical (CSS px / iOS point) coords relative to the surface. The SDK hit-tests + tracks.
|
|
767
|
+
setOnPointer(cb: (phase: number, pointerId: number, x: number, y: number) => void): void
|
|
768
|
+
setClearColor(r: number, g: number, b: number, a: number): void
|
|
769
|
+
|
|
770
|
+
createScene(): number
|
|
771
|
+
destroyScene(sceneId: number): void
|
|
772
|
+
openScene(sceneId: number): void
|
|
773
|
+
closeScene(): void
|
|
774
|
+
sceneSetClearColor(sceneId: number, r: number, g: number, b: number, a: number): void
|
|
775
|
+
addEntityToScene(sceneId: number, entityId: number): void
|
|
776
|
+
removeEntityFromScene(sceneId: number, entityId: number): void
|
|
777
|
+
setLayerYSort(sceneId: number, layer: number, enabled: boolean): void
|
|
778
|
+
|
|
779
|
+
cameraSetPosition(sceneId: number, x: number, y: number): void
|
|
780
|
+
cameraSetZoom(sceneId: number, zoom: number): void
|
|
781
|
+
cameraSetRotation(sceneId: number, deg: number): void
|
|
782
|
+
cameraScreenToWorld(sceneId: number, sx: number, sy: number): Float32Array
|
|
783
|
+
cameraWorldToScreen(sceneId: number, wx: number, wy: number): Float32Array
|
|
784
|
+
|
|
785
|
+
createEntity(): number
|
|
786
|
+
destroyEntity(entityId: number): void
|
|
787
|
+
setPosition(entityId: number, x: number, y: number): void
|
|
788
|
+
setRotation(entityId: number, deg: number): void
|
|
789
|
+
setScale(entityId: number, sx: number, sy: number): void
|
|
790
|
+
setLayer(entityId: number, layer: number): void
|
|
791
|
+
setZ(entityId: number, z: number): void
|
|
792
|
+
setVisible(entityId: number, visible: boolean): void
|
|
793
|
+
getPosition(entityId: number): Float32Array
|
|
794
|
+
|
|
795
|
+
setParent(childId: number, parentId: number, keepWorld: boolean): void
|
|
796
|
+
getParent(entityId: number): number
|
|
797
|
+
getChildCount(entityId: number): number
|
|
798
|
+
getChild(entityId: number, index: number): number
|
|
799
|
+
getWorldPosition(entityId: number): Float32Array
|
|
800
|
+
getWorldMatrix(entityId: number): Float32Array
|
|
801
|
+
worldToLocal(entityId: number, wx: number, wy: number): Float32Array
|
|
802
|
+
localToWorld(entityId: number, lx: number, ly: number): Float32Array
|
|
803
|
+
getLocalTransform(entityId: number): Float32Array
|
|
804
|
+
|
|
805
|
+
setSprite(entityId: number, textureId: number): void
|
|
806
|
+
setSpriteFrame(entityId: number, u0: number, v0: number, u1: number, v1: number): void
|
|
807
|
+
setSpriteFramePx(entityId: number, px: number, py: number, pw: number, ph: number): void
|
|
808
|
+
setSpriteSize(entityId: number, w: number, h: number): void
|
|
809
|
+
setSpriteAnchor(entityId: number, ax: number, ay: number): void
|
|
810
|
+
setSpriteColor(entityId: number, r: number, g: number, b: number): void
|
|
811
|
+
setSpriteOpacity(entityId: number, a: number): void
|
|
812
|
+
setSpriteFlip(entityId: number, flipX: boolean, flipY: boolean): void
|
|
813
|
+
|
|
814
|
+
createTexture(systemId: number, onComplete: (texId: number, w: number, h: number) => void, onReject: (e: any) => void): void
|
|
815
|
+
getTextureWidth(texId: number): number
|
|
816
|
+
getTextureHeight(texId: number): number
|
|
817
|
+
destroyTexture(texId: number): void
|
|
818
|
+
setDefaultFilter(linear: boolean): void
|
|
819
|
+
|
|
820
|
+
// Textures from a _creatorCanvas surface (RGBA8, already rasterized — no decode, so synchronous).
|
|
821
|
+
// See docs/canvas-contract.md.
|
|
822
|
+
createTextureFromCanvas(surfaceId: number): number
|
|
823
|
+
updateTextureFromCanvas(texId: number, surfaceId: number): void
|
|
824
|
+
|
|
825
|
+
defineAnimation(entityId: number, frames: Float32Array, fps: number, loop: boolean): number
|
|
826
|
+
playAnimation(entityId: number, clipId: number): void
|
|
827
|
+
stopAnimation(entityId: number): void
|
|
828
|
+
setAnimationSpeed(entityId: number, speed: number): void
|
|
829
|
+
getAnimationFrame(entityId: number): number
|
|
830
|
+
|
|
831
|
+
createTilemap(textureId: number, cols: number, rows: number, tileW: number, tileH: number, atlasCols: number, atlasRows: number, data: Int32Array): number
|
|
832
|
+
setTile(tilemapId: number, x: number, y: number, index: number): void
|
|
833
|
+
|
|
834
|
+
bulkSetPositions(ids: Uint32Array, xy: Float32Array, count: number): void
|
|
835
|
+
|
|
836
|
+
// physics (Box2D v3; present only in CREATOR_2D_PHYSICS builds — physicsHasSupport() reports it).
|
|
837
|
+
// See docs/2d-physics-plan.md. physicsHasSupport() reports the BUILD, not the world: the world is
|
|
838
|
+
// created lazily by the first physicsCreateBody, so configure() is optional.
|
|
839
|
+
physicsHasSupport(): boolean
|
|
840
|
+
/** Live and non-destructive: an existing world keeps its bodies and takes the new gravity.
|
|
841
|
+
* pixelsPerMeter only applies to a world that doesn't exist yet (global Box2D tolerance). */
|
|
842
|
+
physicsConfigure(gx: number, gy: number, pixelsPerMeter: number, subStepCount: number): void
|
|
843
|
+
setInterpolation(enabled: boolean): void
|
|
844
|
+
/** type 0 contactBegin / 1 contactEnd / 2 sensorBegin / 3 sensorEnd. A contact BEGIN carries the
|
|
845
|
+
* manifold — world point, normal pointing A→B, and the approach speed at impact; the other three
|
|
846
|
+
* carry zeros. (The begin manifold is pre-solve, so its impulses are all zero — `speed` is the
|
|
847
|
+
* pre-solve relative normal velocity, which is the number an impact actually wants.) */
|
|
848
|
+
setOnPhysicsEvent(cb: (entityA: number, entityB: number, type: number, px: number, py: number, nx: number, ny: number, speed: number) => void): void
|
|
849
|
+
physicsCreateBody(entityId: number, motionType: number): number
|
|
850
|
+
physicsRemoveBody(bodyHandle: number): void
|
|
851
|
+
// Shapes carry no `density` (built at density 1, so mass == area — physicsSetMass overrides) and
|
|
852
|
+
// do carry the collision filter. category/mask are 32-bit; 0 means "everything".
|
|
853
|
+
physicsAddBox(bodyHandle: number, hw: number, hh: number, ox: number, oy: number, friction: number, bounce: number, isSensor: boolean, category: number, mask: number): void
|
|
854
|
+
physicsAddCircle(bodyHandle: number, radius: number, ox: number, oy: number, friction: number, bounce: number, isSensor: boolean, category: number, mask: number): void
|
|
855
|
+
physicsAddCapsule(bodyHandle: number, x1: number, y1: number, x2: number, y2: number, radius: number, friction: number, bounce: number, isSensor: boolean, category: number, mask: number): void
|
|
856
|
+
physicsAddSegment(bodyHandle: number, x1: number, y1: number, x2: number, y2: number, friction: number, bounce: number, category: number, mask: number): void
|
|
857
|
+
physicsAddPolygon(bodyHandle: number, pts: Float32Array, count: number, friction: number, bounce: number, isSensor: boolean, category: number, mask: number): void
|
|
858
|
+
/** A polyline of connected segments — long CONCAVE surfaces in one seam-free piece. STATIC bodies
|
|
859
|
+
* only, >= 4 points; the SDK synthesises the tangent points an open chain needs, because Box2D's
|
|
860
|
+
* first and last edges do not collide. One-sided: solid on the right of the point order. */
|
|
861
|
+
physicsAddChain(bodyHandle: number, pts: Float32Array, count: number, isLoop: boolean, friction: number, bounce: number, category: number, mask: number): void
|
|
862
|
+
/** Destroy every shape on a body, keeping the body (id, transform, velocity) — the first half of a
|
|
863
|
+
* live collider rebuild. */
|
|
864
|
+
physicsClearShapes(bodyHandle: number): void
|
|
865
|
+
/** Contact events are OFF per body until this turns them on — otherwise every crate-on-crate pair
|
|
866
|
+
* crosses the bridge every frame. The SDK enables it on the first 'enter'/'exit' listener. */
|
|
867
|
+
physicsSetContactEvents(bodyHandle: number, enabled: boolean): void
|
|
868
|
+
physicsSetLinearVelocity(bodyHandle: number, x: number, y: number): void
|
|
869
|
+
physicsGetLinearVelocity(bodyHandle: number): Float32Array
|
|
870
|
+
physicsSetAngularVelocity(bodyHandle: number, degPerSec: number): void
|
|
871
|
+
physicsGetAngularVelocity(bodyHandle: number): number
|
|
872
|
+
physicsApplyLinearImpulse(bodyHandle: number, x: number, y: number): void
|
|
873
|
+
/** Impulse at a WORLD point — the lever arm becomes angular impulse (a central impulse never
|
|
874
|
+
* spins a body). Mirrors 3D physicsApplyImpulseAt. */
|
|
875
|
+
physicsApplyImpulseAt(bodyHandle: number, x: number, y: number, px: number, py: number): void
|
|
876
|
+
physicsApplyForce(bodyHandle: number, x: number, y: number): void
|
|
877
|
+
/** Teleport the body to its ENTITY's current world transform — how node.position / .rotation reach
|
|
878
|
+
* it. The parent-chain math stays native instead of being re-derived in TS. Snaps prev/cur so the
|
|
879
|
+
* renderer doesn't interpolate across the jump; the body KEEPS its velocity. */
|
|
880
|
+
physicsSetFromEntity(bodyHandle: number): void
|
|
881
|
+
physicsSetFixedRotation(bodyHandle: number, enabled: boolean): void
|
|
882
|
+
physicsSetGravityScale(bodyHandle: number, scale: number): void
|
|
883
|
+
physicsSetLinearDamping(bodyHandle: number, damping: number): void
|
|
884
|
+
physicsSetAngularDamping(bodyHandle: number, damping: number): void
|
|
885
|
+
physicsSetBullet(bodyHandle: number, enabled: boolean): void
|
|
886
|
+
physicsSetEnabled(bodyHandle: number, enabled: boolean): void
|
|
887
|
+
physicsSetAwake(bodyHandle: number, awake: boolean): void
|
|
888
|
+
/** Scales the shape-derived mass data, so the rotational inertia keeps its ratio. <= 0 restores
|
|
889
|
+
* the area-derived default. */
|
|
890
|
+
physicsSetMass(bodyHandle: number, mass: number): void
|
|
891
|
+
physicsGetMass(bodyHandle: number): number
|
|
892
|
+
physicsSetMotionType(bodyHandle: number, motionType: number): void
|
|
893
|
+
physicsSetFriction(bodyHandle: number, friction: number): void
|
|
894
|
+
physicsSetBounce(bodyHandle: number, bounce: number): void
|
|
895
|
+
physicsSetFilter(bodyHandle: number, category: number, mask: number): void
|
|
896
|
+
// Queries. `mask` = the union of group categories the query may hit (0 = everything); `ignore` is
|
|
897
|
+
// a list of ENTITY ids to skip, passed as floats because ids are small ints and that reuses the
|
|
898
|
+
// one buffer helper. Box2D's closest-ray API has no exclusion, hence the explicit list.
|
|
899
|
+
physicsRaycastClosest(x0: number, y0: number, x1: number, y1: number, mask: number, ignore: Float32Array, ignoreCount: number): Float32Array
|
|
900
|
+
/** All hits along the segment, nearest first: maxHits records of [entityId, px, py, nx, ny, fraction]. */
|
|
901
|
+
physicsRaycastAll(x0: number, y0: number, x1: number, y1: number, mask: number, ignore: Float32Array, ignoreCount: number, maxHits: number): Float32Array
|
|
902
|
+
/** Overlap an arbitrary convex shape given as a point cloud + radius (Box2D's b2ShapeProxy form),
|
|
903
|
+
* so one call covers circle / capsule / box / polygon — and the swept test for a moving circle.
|
|
904
|
+
* Returns up to maxHits entity ids. */
|
|
905
|
+
physicsOverlap(pts: Float32Array, count: number, radius: number, mask: number, ignore: Float32Array, ignoreCount: number, maxHits: number): Float32Array
|
|
906
|
+
/** Topmost by DRAW order (layer, then z) — not whatever the broadphase hands back first. */
|
|
907
|
+
physicsOverlapPoint(x: number, y: number, mask: number, ignore: Float32Array, ignoreCount: number): number
|
|
908
|
+
// CharacterController2D (Box2D's kinematic mover). The character steps on the engine's FIXED clock
|
|
909
|
+
// inside the same loop as the bodies, so the SDK does no per-frame work. Capsule ends are in the
|
|
910
|
+
// character's own frame. It also owns a hidden kinematic "shadow" body so raycasts, overlaps and
|
|
911
|
+
// sensors see it — solid shapes strip the reserved character bit from their mask, sensors add it.
|
|
912
|
+
characterCreate(entityId: number, x1: number, y1: number, x2: number, y2: number, radius: number, maxSlopeDeg: number, category: number, mask: number): number
|
|
913
|
+
characterDestroy(charId: number): void
|
|
914
|
+
/** The HORIZONTAL command, world units/s — a per-frame command that EXPIRES once a step consumes it. */
|
|
915
|
+
characterMove(charId: number, x: number): void
|
|
916
|
+
/** Free mode (gravityScale 0): both axes as one expiring command. */
|
|
917
|
+
characterMoveFree(charId: number, x: number, y: number): void
|
|
918
|
+
characterSetVerticalVelocity(charId: number, vy: number): void
|
|
919
|
+
/** LATCH the whole velocity — it persists until a characterMove takes the axis back. */
|
|
920
|
+
characterSetVelocity(charId: number, x: number, y: number): void
|
|
921
|
+
characterSetGravityScale(charId: number, scale: number): void
|
|
922
|
+
characterSetMaxSlope(charId: number, maxSlopeDeg: number): void
|
|
923
|
+
characterSetFilter(charId: number, category: number, mask: number): void
|
|
924
|
+
/** Ignore this entity's one-way surfaces (0 = none) — dropping through a semisolid platform. */
|
|
925
|
+
characterSetDropThrough(charId: number, entityId: number): void
|
|
926
|
+
/** Resize keeping the FEET planted; false = it didn't fit and NOTHING changed, so the caller
|
|
927
|
+
* retries later and that retry is an exact headroom test. */
|
|
928
|
+
characterSetCapsule(charId: number, x1: number, y1: number, x2: number, y2: number, radius: number): boolean
|
|
929
|
+
/** Teleport to the entity's world transform (how node.position reaches a character). Drops fall speed. */
|
|
930
|
+
characterSetFromEntity(charId: number): void
|
|
931
|
+
/** out8 = [velX, velY, groundState (0 ground / 1 slope / 2 air), normalX, normalY, groundEntity,
|
|
932
|
+
* collisionCount, 0]. The velocity is MEASURED, not commanded. */
|
|
933
|
+
characterGetState(charId: number, out: Float32Array): void
|
|
934
|
+
/** maxN records of [entityId, normalX, normalY] — what the mover pushed out of this step. */
|
|
935
|
+
characterGetCollisions(charId: number, maxN: number): Float32Array
|
|
936
|
+
/** Mark a body's surfaces one-way: solid only from the side (nx, ny) points to, within arcDeg.
|
|
937
|
+
* Honoured by the mover and, via a native pre-solve callback, by ordinary rigid bodies. */
|
|
938
|
+
physicsSetOneWay(bodyHandle: number, nx: number, ny: number, arcDeg: number, enabled: boolean): void
|
|
939
|
+
pickSprite(sceneId: number, wx: number, wy: number): number
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// ---- multiplayer transport (creator-net / yojimbo) -------------------------------------------
|
|
943
|
+
// A byte pipe pumped on the JS thread (docs/multiplayer-plan.md). Present only on hosts built
|
|
944
|
+
// with CREATOR_PKG_NET (desktop, the 3d/full Android variants, iOS); the SDK feature-detects it.
|
|
945
|
+
// One endpoint per process: `listen` (server / host) or `connect` (client), never both.
|
|
946
|
+
var _creatorNet: {
|
|
947
|
+
/** What the exe was launched as (`--server --port N` / `--connect ADDR`), or null. */
|
|
948
|
+
launch(): { role: string, address: string, port: number, maxClients: number } | null
|
|
949
|
+
/** Serve on every interface at `port` (wildcard public address). */
|
|
950
|
+
listen(port: number, maxClients: number): boolean
|
|
951
|
+
/** Insecure (dev / LAN) connect to "ip:port"; the outcome arrives as a poll record. */
|
|
952
|
+
connect(address: string): boolean
|
|
953
|
+
disconnect(): void
|
|
954
|
+
kick(client: number): void
|
|
955
|
+
/** Queue a payload: channel 0 reliable-ordered, 1 unreliable; `client` ignored on a client.
|
|
956
|
+
* A string travels as UTF-8 text and arrives as a string; bytes arrive as an ArrayBuffer. */
|
|
957
|
+
send(client: number, channel: number, data: string | ArrayBuffer | Uint8Array): boolean
|
|
958
|
+
/** Pump once and return every record since the last call as a flat array of 4-tuples
|
|
959
|
+
* [kind, client, arg, payload] — kind 1 connected · 2 disconnected · 3 message · 4 connectFailed;
|
|
960
|
+
* arg = channel (message) or reason code; payload = string | ArrayBuffer | null. */
|
|
961
|
+
poll(): any[] | null
|
|
962
|
+
/** 0 idle · 1 client · 2 server */
|
|
963
|
+
mode(): number
|
|
964
|
+
/** Client: 0 disconnected · 1 connecting · 2 connected · 3 failed. A listening server: 2. */
|
|
965
|
+
state(): number
|
|
966
|
+
/** [connected, rttMs, lossPct, sentKbps, receivedKbps] for a slot (server) / the link (client). */
|
|
967
|
+
clientInfo(client: number): Float32Array
|
|
968
|
+
/** yojimbo network simulator on this side of the wire. */
|
|
969
|
+
simulate(latencyMs: number, jitterMs: number, lossPercent: number): void
|
|
970
|
+
reasonString(reason: number, serverSide: boolean): string
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// ---- navigation meshes (creator-nav / Recast+Detour) -----------------------------------------
|
|
974
|
+
// Runtime only (docs/navmesh-plan.md §5): load a baked `.navmesh` (LNAV) from a fetch system id,
|
|
975
|
+
// query it, run a DetourCrowd of agents one fixed step at a time. Present on hosts built with
|
|
976
|
+
// CREATOR_PKG_NAV (desktop, the 3d/full Android variants, iOS) and on every web host through the
|
|
977
|
+
// wasm build; the SDK feature-detects it. Parameter blocks are fixed-order Float32Arrays
|
|
978
|
+
// (creator-nav.h CNAV_AGENT_* / CNAV_READ_*). Handles (meshId / crowdId, from 1) die with the world.
|
|
979
|
+
var _creatorNav: {
|
|
980
|
+
/** Web hosts only: loads the wasm lazily. Absent on native hosts — call it when present. */
|
|
981
|
+
ready?(): Promise<void>
|
|
982
|
+
lastError(): string
|
|
983
|
+
/** LNAV bytes already fetched (the createGlb pattern) → meshId, 0 on failure. */
|
|
984
|
+
load(systemId: number): number
|
|
985
|
+
unload(meshId: number): void
|
|
986
|
+
/** The file's JSON header: agent size, cell, bounds, stats, `meta` (the CLI's provenance). */
|
|
987
|
+
header(meshId: number): string
|
|
988
|
+
polyCount(meshId: number): number
|
|
989
|
+
setAreaCost(meshId: number, area: number, cost: number): void
|
|
990
|
+
/** Straight path from → to into `out` (xyz per corner); returns the corner count, NEGATIVE when
|
|
991
|
+
* the path is partial (the target is unreachable — it ends at the closest polygon). `ex <= 0`
|
|
992
|
+
* = default search extents. */
|
|
993
|
+
findPath(meshId: number, fx: number, fy: number, fz: number, tx: number, ty: number, tz: number, ex: number, ey: number, ez: number, include: number, exclude: number, maxCorners: number, out: Float32Array): number
|
|
994
|
+
nearest(meshId: number, x: number, y: number, z: number, ex: number, ey: number, ez: number, include: number, exclude: number, out: Float32Array): boolean
|
|
995
|
+
/** Walkability ray along the surface; true = BLOCKED, out = [hit xyz, wall normal xyz]. */
|
|
996
|
+
raycast(meshId: number, fx: number, fy: number, fz: number, tx: number, ty: number, tz: number, include: number, exclude: number, out: Float32Array): boolean
|
|
997
|
+
/** `radius <= 0` = anywhere on the mesh; deterministic per seed. */
|
|
998
|
+
randomPoint(meshId: number, cx: number, cy: number, cz: number, radius: number, seed: number, include: number, exclude: number, out: Float32Array): boolean
|
|
999
|
+
/** The polygon mesh as a triangle soup (xyz per vertex) for debug drawing. */
|
|
1000
|
+
debugTriangles(meshId: number): Float32Array
|
|
1001
|
+
crowdCreate(meshId: number, maxAgents: number, maxRadius: number): number
|
|
1002
|
+
crowdDestroy(crowdId: number): void
|
|
1003
|
+
/** → the agent's slot (0..maxAgents-1), -1 when full / off the mesh. */
|
|
1004
|
+
crowdAdd(crowdId: number, x: number, y: number, z: number, params: Float32Array): number
|
|
1005
|
+
crowdRemove(crowdId: number, agent: number): void
|
|
1006
|
+
crowdSetParams(crowdId: number, agent: number, params: Float32Array): void
|
|
1007
|
+
crowdSetTarget(crowdId: number, agent: number, x: number, y: number, z: number): boolean
|
|
1008
|
+
crowdSetVelocity(crowdId: number, agent: number, vx: number, vy: number, vz: number): void
|
|
1009
|
+
crowdResetTarget(crowdId: number, agent: number): void
|
|
1010
|
+
crowdWarp(crowdId: number, agent: number, x: number, y: number, z: number): boolean
|
|
1011
|
+
/** Once per fixed step. */
|
|
1012
|
+
crowdUpdate(crowdId: number, dt: number): void
|
|
1013
|
+
/** Every slot into `out` (CNAV_AGENT_READ_STRIDE floats each); returns maxAgents. */
|
|
1014
|
+
crowdRead(crowdId: number, out: Float32Array): number
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// ---- Game audio (creator-audio) ----------------------------------------------------------------
|
|
1018
|
+
// docs/audio-plan.md. Whole clips decoded up front, a fixed voice pool (play allocates nothing),
|
|
1019
|
+
// 3D sources the engine follows per frame, mixer buses with insert effects, reverb zones,
|
|
1020
|
+
// occlusion. OPTIONAL as a block: the SDK gates on `typeof _creatorAudio !== 'undefined' &&
|
|
1021
|
+
// hasSupport()` and stays inert (silent Sound, inert Voice) without it. Present on hosts built with
|
|
1022
|
+
// CREATOR_PKG_AUDIO (desktop first; Android / Apple pending — parity `audio-game`). The headless
|
|
1023
|
+
// renderer provides a RECORDER (plays are logged, nothing is mixed). Every parameter block is a
|
|
1024
|
+
// fixed-order Float32Array (creator-audio.h CAUD_SRC_* / the effect param orders).
|
|
1025
|
+
var _creatorAudio: {
|
|
1026
|
+
hasSupport(): boolean
|
|
1027
|
+
/** Decode the bytes behind a fetch system id (WAV / MP3 / FLAC / OGG Vorbis) on the engine's
|
|
1028
|
+
* loader thread; mono unless `stereo`. onDone(clipId, durationSeconds, channels). */
|
|
1029
|
+
loadClip(systemId: number, stereo: boolean, onDone: (clipId: number, duration: number, channels: number) => void, onReject: (message: string) => void): void
|
|
1030
|
+
releaseClip(clipId: number): void
|
|
1031
|
+
/** Bus id by name (-1 unknown); 0 master, 1 sfx, 2 music, 3 ui, 4 voice. */
|
|
1032
|
+
busId(name: string): number
|
|
1033
|
+
/** Creates (or finds) an app-defined bus under master. -1 when the 16 slots are full. */
|
|
1034
|
+
createBus(name: string): number
|
|
1035
|
+
setBusVolume(bus: number, volume: number): void
|
|
1036
|
+
setBusMuted(bus: number, muted: boolean): void
|
|
1037
|
+
/** kind 1 reverb [roomSize, damping, width, mix, preDelay] · 2 echo [delay, decay, mix] ·
|
|
1038
|
+
* 3 lowpass [cutoffHz]; an empty array turns the effect off. Changes are smoothed. */
|
|
1039
|
+
setBusEffect(bus: number, kind: number, params: Float32Array): void
|
|
1040
|
+
stopBus(bus: number, fade: number): void
|
|
1041
|
+
/** A 3D emitter. `attachSource` binds it to an entity the engine follows every frame;
|
|
1042
|
+
* `setSourcePosition` places an unbound one (playAt). */
|
|
1043
|
+
createSource(): number
|
|
1044
|
+
attachSource(sourceId: number, entityId: number): void
|
|
1045
|
+
/** [minDistance, maxDistance, rolloff (0 none 1 inverse 2 linear 3 exp), coneInnerDeg,
|
|
1046
|
+
* coneOuterDeg, coneOuterGain, doppler, spread, occlusion (0/1), bus]. */
|
|
1047
|
+
setSourceParams(sourceId: number, params: Float32Array): void
|
|
1048
|
+
setSourcePosition(sourceId: number, x: number, y: number, z: number): void
|
|
1049
|
+
stopSource(sourceId: number, fade: number): void
|
|
1050
|
+
sourceVoices(sourceId: number): number
|
|
1051
|
+
destroySource(sourceId: number): void
|
|
1052
|
+
/** The listener entity; 0 = the active scene camera (the default). */
|
|
1053
|
+
setListener(entityId: number): void
|
|
1054
|
+
setListenerOptions(dopplerFactor: number): void
|
|
1055
|
+
/** HRTF binaural rendering for the `maxVoices` nearest spatial voices (headphones); the rest keep panning. */
|
|
1056
|
+
setHrtf(enabled: boolean, maxVoices: number): void
|
|
1057
|
+
/** Whether the engine's time scale (Time.scale) also pitches the sfx bus. Default false (pause = mute only). */
|
|
1058
|
+
setTimeScalePitch(enabled: boolean): void
|
|
1059
|
+
/** → a voice token (0 = nothing played: the pool refused, the clip is not ready). bus -1 = the
|
|
1060
|
+
* source's bus (sfx for 2D). pan is 2D only. */
|
|
1061
|
+
play(clipId: number, sourceId: number, bus: number, volume: number, pitch: number, loop: boolean, priority: number, fadeIn: number, startAt: number, pan: number): number
|
|
1062
|
+
setVoiceVolume(token: number, volume: number): void
|
|
1063
|
+
setVoicePitch(token: number, pitch: number): void
|
|
1064
|
+
setVoicePan(token: number, pan: number): void
|
|
1065
|
+
stopVoice(token: number, fade: number): void
|
|
1066
|
+
voicePlaying(token: number): boolean
|
|
1067
|
+
voiceTime(token: number): number
|
|
1068
|
+
/** THE ended listener (single slot per JS world): called once per tick with the tokens of the
|
|
1069
|
+
* voices that ended since the previous tick — natural end, stop, steal. */
|
|
1070
|
+
setOnEnded(callback: ((tokens: Float32Array) => void) | null): void
|
|
1071
|
+
stopAll(fade: number): void
|
|
1072
|
+
/** A reverb volume: shape 0 box (dims = full size) / 1 sphere (dims[0] = diameter), in the
|
|
1073
|
+
* entity's local units; `blend` metres of crossfade inside the border; reverb params as for
|
|
1074
|
+
* setBusEffect kind 1. The listener inside blends the zone's reverb onto `bus`. */
|
|
1075
|
+
createZone(): number
|
|
1076
|
+
attachZone(zoneId: number, entityId: number): void
|
|
1077
|
+
setZone(zoneId: number, shape: number, dims: Float32Array, blend: number, bus: number, reverb: Float32Array): void
|
|
1078
|
+
destroyZone(zoneId: number): void
|
|
1079
|
+
/** [voicesPlaying, voicesMono, voicesStereo, stolen, clips, clipBytes, peak, sampleRate, listenerZone, zoneBlend, hrtfVoices]. */
|
|
1080
|
+
stats(): Float32Array
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// ---- UI engine (creator-ui) ------------------------------------------------------------------
|
|
1084
|
+
var _creatorUI: {
|
|
1085
|
+
// Global back-press fallback (app.onBackPressed): a PROPERTY the SDK writes, not a call —
|
|
1086
|
+
// the engine reads it off this world's _creatorUI object at the END of its back chain
|
|
1087
|
+
// (widget → destination → pager → router → this), so it dies with the world's context.
|
|
1088
|
+
// Old hosts never read it and the handler is silently inert there.
|
|
1089
|
+
_backButtonCallback?: () => void
|
|
1090
|
+
openScreen(screen: object): void
|
|
1091
|
+
closeScreen(): void
|
|
1092
|
+
updateStyle(nodeId: number, prop: string, value: any): void
|
|
1093
|
+
mergeStyle(nodeId: number, style: object): void
|
|
1094
|
+
// Toggle a user style class (a `$`-block declared in .style()) on a node. `name` arrives
|
|
1095
|
+
// WITHOUT the leading `$`. Class state CASCADES down the node tree: a class set on a node is
|
|
1096
|
+
// active on all its descendants within the same root (screens/widgets are separate roots) —
|
|
1097
|
+
// implemented ONCE in creator-ui's setNodeClass (docs/style-class-cascade-plan.md); hosts must
|
|
1098
|
+
// NOT layer their own inheritance on top. `$pressed`/`$focused` are reserved cascading classes
|
|
1099
|
+
// hosts toggle alongside the built-in onPressed/onFocused (creator-ui setNodePressed/Focused).
|
|
1100
|
+
setClass(nodeId: number, name: string, enabled: boolean): void
|
|
1101
|
+
|
|
1102
|
+
// Theme variables (docs/ui-theme-plan.md). MERGES `values` into the app theme table and
|
|
1103
|
+
// re-resolves live styles: keys are var names (`var(--name)` in style values reads them;
|
|
1104
|
+
// the four `comfort-*` keys are the comfort knobs), null removes a key, numbers are lengths
|
|
1105
|
+
// (px). Env names (safe-*, vw/vh/vmin/vmax) are reserved — hosts ignore writes to them.
|
|
1106
|
+
// Optional during rollout: the SDK feature-detects.
|
|
1107
|
+
setTheme?(values: Record<string, string | number | null>): void
|
|
1108
|
+
|
|
1109
|
+
// Content-property push. Props: "value" (input/textarea text), "focus" (boolean — focus/blur
|
|
1110
|
+
// the input, opening/dismissing the keyboard; rides this channel so programmatic focus needs
|
|
1111
|
+
// no new ABI method), plus element-specific ones ("src", "text", …).
|
|
1112
|
+
// An image "src" (here and at creation) is a url string, { _id } (a host buffer), { svg },
|
|
1113
|
+
// { canvasSurface } (a baked Canvas), or { scene2d: sceneId } — a LIVE 2D scene the host draws
|
|
1114
|
+
// into the node's laid-out box every frame with the scene's own camera (native: c2dDrawSceneGL
|
|
1115
|
+
// into a per-node framebuffer; no intrinsic size, the scene needs no openScene). The engine's
|
|
1116
|
+
// simulation must still step each frame for it (native: c2dTick when nothing is presented).
|
|
1117
|
+
updateNode(nodeId: number, prop: string, value: any): void
|
|
1118
|
+
setSourceRect(nodeId: number, x: number, y: number, w: number, h: number): void
|
|
1119
|
+
|
|
1120
|
+
// Canvas.update() → live-refresh every UIImage(canvas) node currently showing this baked surface:
|
|
1121
|
+
// the host re-reads the re-rasterized pixels into the image view WITHOUT a relayout (the surface
|
|
1122
|
+
// keeps its id and size across an update; a resize goes through a full `src` re-assign). Optional
|
|
1123
|
+
// during rollout — the SDK feature-detects and falls back to re-assigning `src`.
|
|
1124
|
+
refreshCanvasSurface?(surfaceId: number): void
|
|
1125
|
+
|
|
1126
|
+
// Font registration is fire-and-forget in practice: hosts load the face, then re-measure /
|
|
1127
|
+
// re-layout when it lands (docs/font-system-plan.md — swap is the fallback; boot faces are
|
|
1128
|
+
// prefetched via the bundle's `// fonts:` header). The callbacks stay on the wire for old
|
|
1129
|
+
// bundles that gate on them — hosts must keep invoking onComplete. Repeated registration of
|
|
1130
|
+
// the same (family, weight, style) is a cheap no-op — hosts dedupe.
|
|
1131
|
+
registerFont(fontFamily: string, url: string, options: any, onComplete: () => void, onReject: () => void): void
|
|
1132
|
+
// Preferred container format for CDN-served faces: "woff2" on browser hosts, absent (= "ttf")
|
|
1133
|
+
// on native/headless. The font() macro's generated registration code reads it to pick the
|
|
1134
|
+
// file extension; the `// fonts:` header carries a `{fmt}` placeholder for the same choice.
|
|
1135
|
+
fontFormat?: "woff2" | "ttf"
|
|
1136
|
+
|
|
1137
|
+
isButtonPressed(nodeId: number): boolean
|
|
1138
|
+
|
|
1139
|
+
registerTouchStartEvent(callback: (...args: any) => void): void
|
|
1140
|
+
registerTouchEndEvent(callback: (...args: any) => void): void
|
|
1141
|
+
registerResizeEvent(callback: (...args: any) => void): void
|
|
1142
|
+
// Current display size [width, height] in logical px — the same values the resize event delivers.
|
|
1143
|
+
// Surfaced as device.width / device.height. Optional: hosts that don't track it (headless) omit it,
|
|
1144
|
+
// and the getters fall back to 0.
|
|
1145
|
+
getDisplaySize?(): [number, number]
|
|
1146
|
+
|
|
1147
|
+
getTextValue(nodeId: number): string
|
|
1148
|
+
|
|
1149
|
+
// Absolute device-space rect [left, top, width, height] of a laid-out node, in logical px —
|
|
1150
|
+
// the same space UIWidget top/left position in — INCLUDING scroll offsets: computed live at
|
|
1151
|
+
// call time, never cached from layout events. null (or undefined) when the node isn't
|
|
1152
|
+
// mounted/laid out. Backs el.getBoundingClientRect(), the widget-anchoring primitive
|
|
1153
|
+
// (dropdowns, popovers, tooltips — docs/ui-components-plan.md §3.2). Optional: the SDK
|
|
1154
|
+
// feature-detects and returns null on hosts without it.
|
|
1155
|
+
getBoundingClientRect?(nodeId: number): [number, number, number, number] | null
|
|
1156
|
+
|
|
1157
|
+
insertNode(index: number, nodeId: number, childNode: any): void
|
|
1158
|
+
removeNode(nodeId: number, childNode: any): void
|
|
1159
|
+
setContent(nodeId: number, oldChildren: any[], children: any[]): void
|
|
1160
|
+
|
|
1161
|
+
animateTo(nodeId: number, style: any): void
|
|
1162
|
+
animateFrom(nodeId: number, style: any): void
|
|
1163
|
+
toast(msg: string): void
|
|
1164
|
+
|
|
1165
|
+
// Router over destinations. On hosts that implement openView (below), `screen`/`view` is any
|
|
1166
|
+
// view descriptor (not just a screen object) and the extra `transition` args apply; legacy
|
|
1167
|
+
// hosts receive screen objects only and ignore the extras.
|
|
1168
|
+
routerOpen(view: any, onChange: (view: any) => void, showBackButton: boolean): void
|
|
1169
|
+
routerPush(view: any, transition?: string | object): void
|
|
1170
|
+
routerReplace(view: any, transition: string | object): void
|
|
1171
|
+
routerPop(index: number, transition?: string | object): void
|
|
1172
|
+
routerHide(): void
|
|
1173
|
+
routerRestore(): void
|
|
1174
|
+
|
|
1175
|
+
// ---- Presentable navigation (docs/navigation-presentable-plan.md) --------------------------
|
|
1176
|
+
// One visible destination at a time. `view` is either a screen node object (type "screen")
|
|
1177
|
+
// or a descriptor:
|
|
1178
|
+
// { type: "scene3d", sceneId } { type: "scene2d", sceneId }
|
|
1179
|
+
// { type: "native", viewName, params, viewId } { type: "videoView", node }
|
|
1180
|
+
// Descriptors carry `_p` (the SDK Presentable instance): hand the SAME object back through
|
|
1181
|
+
// router onChange, and fire its `ol`/`cl` arrays on present/dismiss (screens carry ol/cl
|
|
1182
|
+
// themselves). Presenting a scene descriptor includes activating the engine (the openScene
|
|
1183
|
+
// equivalent); while covered, scene rendering pauses. `transition` is a TransitionName string
|
|
1184
|
+
// or a TransitionSpec object (see sdk/src/ui/presentable.ts).
|
|
1185
|
+
// Optional during the migration: the SDK feature-detects openView and falls back to
|
|
1186
|
+
// openScreen/openScene; hosts implementing openView should keep openScreen/routerPush(screen)
|
|
1187
|
+
// as thin aliases into it for previously compiled bundles.
|
|
1188
|
+
openView?(view: object, transition: string | object): void
|
|
1189
|
+
closeView?(): void
|
|
1190
|
+
|
|
1191
|
+
// NativeView plugin channel (host `registerView(name, factory)` capabilities). `args`, the
|
|
1192
|
+
// result, and event payloads are JSON strings. Events are delivered by invoking the arrays in
|
|
1193
|
+
// the element's `nvl[event]` or via its `_emitViewEvent(event, json)`.
|
|
1194
|
+
isViewSupported?(name: string): boolean
|
|
1195
|
+
viewCall?(viewId: number, method: string, args: string, onComplete: (result?: string) => void, onError: (err: string) => void): void
|
|
1196
|
+
|
|
1197
|
+
// `owner` (a view descriptor) binds the widget to a destination: it mounts inside the owner's
|
|
1198
|
+
// page — shows/hides with it and rides its transition. Omitted = global overlay (legacy
|
|
1199
|
+
// behavior; legacy hosts ignore the arg).
|
|
1200
|
+
showWidget(widget: object, owner?: object): void
|
|
1201
|
+
hideWidget(widget: object): void
|
|
1202
|
+
|
|
1203
|
+
vlistMount(jsNode: any, key: string, subtree: any): void
|
|
1204
|
+
vlistSetKeys(jsNode: any, keys: string[], estimates: number[]): void
|
|
1205
|
+
vlistInsertKeys(jsNode: any, index: number, keys: string[], estimates: number[]): void
|
|
1206
|
+
vlistInvalidate(jsNode: any, k: string): void
|
|
1207
|
+
vlistRemoveKeys(jsNode: any, keys: string[]): void
|
|
1208
|
+
command(jsNode: any, command: string, ...args: any): void
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
// ---- Platform utilities ----------------------------------------------------------------------
|
|
1212
|
+
var _creatorUtils: {
|
|
1213
|
+
// `fetchOptions.body` is either a string or a FormData: an object carrying `_entries`, an array
|
|
1214
|
+
// of [key, value, filename?]. A `value` object carrying a numeric `_id` is binary (that's the
|
|
1215
|
+
// host buffer id — SDK `File` and `FetchResponse` both expose it under that key); anything else
|
|
1216
|
+
// is a text field. Same `_id` convention as an image `src` object (see _creatorUI.updateNode).
|
|
1217
|
+
fetch(url: string, fetchOptions: any, onComplete: (systemId: number, statusCode: number) => void, onReject: () => void): void
|
|
1218
|
+
fetchLocal(path: string): number
|
|
1219
|
+
fetchToJson(systemId: number): any
|
|
1220
|
+
fetchSlice(systemId: number, start: number, end: number): any
|
|
1221
|
+
fetchToText(systemId: number): string
|
|
1222
|
+
/** The fetched bytes as a Uint8Array copy (a `.terrain` file, any binary the SDK parses itself).
|
|
1223
|
+
* Optional: an older host has only the text/JSON readers (Terrain.load throws there). */
|
|
1224
|
+
fetchToBytes?(systemId: number): Uint8Array
|
|
1225
|
+
disposeFetch(systemId: number): void
|
|
1226
|
+
// ---- Local filesystem (the SDK `files` global) ----------------------------------------------
|
|
1227
|
+
// The read/write/delete half of `fetchLocal`, for hosts where the app OWNS a filesystem
|
|
1228
|
+
// (desktop). All five are OPTIONAL and stand or fall together: a sandboxed host (web, mobile)
|
|
1229
|
+
// implements none of them and `files.supported` is false there.
|
|
1230
|
+
//
|
|
1231
|
+
// ASYNC, like `fetch`: file IO must not block the frame, so each takes an onComplete/onReject
|
|
1232
|
+
// pair (the SDK turns them into a promise) and the host does the work off the JS thread. Hosts
|
|
1233
|
+
// must keep the ops ORDERED — two appends to one file settle in call order — so a queue, not a
|
|
1234
|
+
// thread per call. Exactly one handle is ever settled.
|
|
1235
|
+
//
|
|
1236
|
+
// PATH POLICY, identical for all five and owned by the host: an ABSOLUTE path is used verbatim;
|
|
1237
|
+
// a RELATIVE one is resolved against the app's OWN folder — never the process cwd — which for a
|
|
1238
|
+
// packaged desktop app is the exe's directory, one of the directories `fetchLocal` searches by
|
|
1239
|
+
// name. So `writeLocal("save.json", …)` and `fetchLocal("save.json")` are a pair.
|
|
1240
|
+
/** Write a file, creating the parent folders. `append` adds to the end instead of replacing.
|
|
1241
|
+
* `data` is text (written as UTF-8), raw bytes (Uint8Array / ArrayBuffer), or a host buffer
|
|
1242
|
+
* object carrying `_id` (an SDK `File` / `FetchResponse` — so a picked or generated file is
|
|
1243
|
+
* saved as it is); the bytes are only valid for the duration of the call, so a host that
|
|
1244
|
+
* defers the write copies them first. The core drops the path's cached `fetchLocal` id, so
|
|
1245
|
+
* the next read sees the new bytes. */
|
|
1246
|
+
writeLocal?(path: string, data: string | Uint8Array | ArrayBuffer | { _id: number }, append: boolean, onComplete: () => void, onReject: (err: Error) => void): void
|
|
1247
|
+
/** The whole file as bytes, or null when there is no such file. Unlike `fetchLocal` this
|
|
1248
|
+
* re-reads every call and holds nothing — no buffer id to dispose. Only a real failure
|
|
1249
|
+
* (an unreadable file) rejects; "not there" is a null result. */
|
|
1250
|
+
readLocalBytes?(path: string, onComplete: (bytes: Uint8Array | null) => void, onReject: (err: Error) => void): void
|
|
1251
|
+
/** The whole file decoded as UTF-8 text, or null when there is no such file. */
|
|
1252
|
+
readLocalText?(path: string, onComplete: (text: string | null) => void, onReject: (err: Error) => void): void
|
|
1253
|
+
/** Delete a file, or an EMPTY directory; `recursive` also deletes a directory's contents.
|
|
1254
|
+
* Deleting something that is already gone SUCCEEDS — the post-condition is what matters. */
|
|
1255
|
+
deleteLocal?(path: string, recursive: boolean, onComplete: () => void, onReject: (err: Error) => void): void
|
|
1256
|
+
/** Create a directory and any missing parents. An existing directory is success. */
|
|
1257
|
+
mkdirLocal?(path: string, onComplete: () => void, onReject: (err: Error) => void): void
|
|
1258
|
+
openFilePicker(onComplete: (res: any) => void, onReject: () => void, multiple: boolean, accept?: string): void
|
|
1259
|
+
// Present the OS media share sheet for a host buffer (`systemId` — a File/response id), with an
|
|
1260
|
+
// optional caption. iOS: the share sheet also offers "Save to Files"/Photos. Web: saves (downloads)
|
|
1261
|
+
// the file. Backs the SDK `share(media, text?)`.
|
|
1262
|
+
shareMedia(systemId: number, text?: string): void
|
|
1263
|
+
|
|
1264
|
+
/** Prompt for camera permission (resolve = granted, reject = denied). Shared by everything that
|
|
1265
|
+
* needs the camera — ARScene.prepare, QRScanner, CameraView — hence a platform utility rather
|
|
1266
|
+
* than a 3D-engine call (it moved off `_creator` 2026-07-15). Optional: hosts whose view
|
|
1267
|
+
* factory prompts on its own (web getUserMedia) don't implement it and the SDK resolves
|
|
1268
|
+
* immediately, so callers go through `_requestCameraPermission()`. */
|
|
1269
|
+
requestCamera?(onComplete: () => void, onReject: () => void): void
|
|
1270
|
+
|
|
1271
|
+
// (openScanner/closeScanner removed 2026-07-15 — QRScanner rides the registered "qrScanner"
|
|
1272
|
+
// NativeView; hosts keep the old handlers only for previously compiled bundles.)
|
|
1273
|
+
// ---- Input (docs/input-plan.md — keyboard / mouse / gamepad behind the SDK `Input` global) ----
|
|
1274
|
+
// Design: a BUTTON is anything that goes down and up — keyboard keys, mouse buttons, gamepad
|
|
1275
|
+
// buttons — and they share ONE code vocabulary (KeyboardEvent.code + "MouseLeft|Right|Middle|
|
|
1276
|
+
// Back|Forward" + the W3C standard-gamepad "GamepadSouth|East|West|North|L1|R1|L2|R2|Select|
|
|
1277
|
+
// Start|L3|R3|Up|Down|Left|Right"), one held-poll and one event pair. Continuous signals (mouse
|
|
1278
|
+
// motion, sticks, triggers) are numbered channels behind one poll. Bindings/axes/edge detection
|
|
1279
|
+
// are SDK-side; hosts only report physical state.
|
|
1280
|
+
/** Is this button held right now? `gamepad` (0..3) scopes a Gamepad* code to one pad; omitted =
|
|
1281
|
+
* any connected pad. Keyboard/mouse codes ignore it. */
|
|
1282
|
+
inputKey: (code: string, gamepad?: number) => boolean
|
|
1283
|
+
/** Continuous input poll by channel id (SDK `InputChannel`): 0 MouseX, 1 MouseY (logical px,
|
|
1284
|
+
* last known cursor position inside the viewport), 2 MouseDX, 3 MouseDY (motion accumulated
|
|
1285
|
+
* during the PREVIOUS frame — unaccelerated/raw where the OS offers it, counts while locked),
|
|
1286
|
+
* 4 WheelX, 5 WheelY (wheel notches, previous frame), 6 PointerLocked (0/1), 7 GamepadCount,
|
|
1287
|
+
* 8 PointerOnUI (0/1: the primary pointer went DOWN on something the UI claimed — an
|
|
1288
|
+
* interactive node, a scrollable, an editable, a modal backdrop — and is still held; stays 1
|
|
1289
|
+
* wherever the cursor goes until the release, so a drag that started on a HUD control never
|
|
1290
|
+
* becomes camera look; always 0 while pointer-locked and for touch-only hosts without a UI claim);
|
|
1291
|
+
* gamepad p at 16 + 16·p: +0 Connected, +1 LeftX, +2 LeftY, +3 RightX, +4 RightY (−1..1,
|
|
1292
|
+
* +Y = down like the web), +5 LeftTrigger, +6 RightTrigger (0..1). Unknown channel → 0.
|
|
1293
|
+
* "Previous frame" = the host's own frame boundary (the event pump / rAF / fixed step), so
|
|
1294
|
+
* every read within one frame agrees. Optional: a host without it has no pointer/gamepad. */
|
|
1295
|
+
inputRead?(channel: number): number
|
|
1296
|
+
/** Request (true) / release (false) pointer lock: hide + confine the cursor, keep MouseDX/DY
|
|
1297
|
+
* flowing (FPS look). Returns whether the request was accepted now (web needs a user gesture);
|
|
1298
|
+
* the eventual state is channel 6. Hosts release on focus loss and re-acquire on focus. */
|
|
1299
|
+
inputSetPointerLock?(on: boolean): boolean
|
|
1300
|
+
/** Register THE input-event listener (single slot per JS world, like registerAppEvent — the SDK
|
|
1301
|
+
* fans out). kind: 0 keydown, 1 keyup, 2 gamepadconnected, 3 gamepaddisconnected. `code` is the
|
|
1302
|
+
* button code above ("" for connect events); `gamepad` the pad index for Gamepad* codes /
|
|
1303
|
+
* connect events, −1 otherwise; `repeat` 1 for an OS auto-repeat keydown. Delivered on the JS
|
|
1304
|
+
* thread no later than the end of the frame it arrived in — i.e. always before the NEXT
|
|
1305
|
+
* setLoop tick (creator-pkg drains its dispatch queue after the frame's timers, so a poll can
|
|
1306
|
+
* see the new state one tick before the event; web/headless deliver synchronously). */
|
|
1307
|
+
registerInputEvent?(callback: (kind: number, code: string, gamepad: number, repeat: number) => void): void
|
|
1308
|
+
// ---- World control (run/restart/quit — the platform's `location` analog) --------------------
|
|
1309
|
+
// Worlds carry two host-tracked bits: an IDENTITY (project uuid) and a TRUST flag. The host's
|
|
1310
|
+
// own boot world (the bundled launcher) is trusted; a world created by `run` is trusted only
|
|
1311
|
+
// when its declared uuid is on the host's trusted-launcher allowlist AND the caller was
|
|
1312
|
+
// trusted itself. Push registration attribution reads the identity (docs/push-plan.md).
|
|
1313
|
+
/** Swap in a new project world. `projectUuid` declares the new world's identity — honored
|
|
1314
|
+
* ONLY when the calling world is trusted (launchers); silently dropped otherwise. `url`
|
|
1315
|
+
* (any caller — the caller already controls the code it runs) is the new world's
|
|
1316
|
+
* launchUrl: a string sets it, null clears it, omitted leaves it unchanged. */
|
|
1317
|
+
run(systemId: number, onReject: () => void, projectUuid?: string, url?: string | null): void
|
|
1318
|
+
/** Re-run the CURRENT world's bundle in a fresh world — `location.reload()`. Identity and
|
|
1319
|
+
* trust are inherited (the host re-evaluates bytes it already holds, so nothing is
|
|
1320
|
+
* spoofable). `url`: string sets the new launchUrl, null clears it, omitted keeps the
|
|
1321
|
+
* current one (a plain reload). If the re-run throws, the current world stays live. */
|
|
1322
|
+
restart?(url?: string | null): void
|
|
1323
|
+
/** Leave the current app. A world launched by `run` returns to the caller's boot bundle
|
|
1324
|
+
* (launch URL cleared, boot identity/trust restored). The boot world itself has no caller —
|
|
1325
|
+
* the host's app-exit hook fires instead (Android backgrounds the task; hosts that can't
|
|
1326
|
+
* exit programmatically, iOS/desktop, register nothing and the call is a no-op). */
|
|
1327
|
+
quit?(): void
|
|
1328
|
+
|
|
1329
|
+
animate(callback: (val: number) => void, duration: number): number
|
|
1330
|
+
stopAnimation(id: number): void
|
|
1331
|
+
pauseAnimation(id: number): void
|
|
1332
|
+
resumeAnimation(id: number): void
|
|
1333
|
+
|
|
1334
|
+
localStorageGetValue(key: string): string | null
|
|
1335
|
+
localStorageSetValue(key: string, value: string): void
|
|
1336
|
+
localStorageRemoveValue(key: string): void
|
|
1337
|
+
|
|
1338
|
+
websocketOpen(url: string, onWebsocketMessage: (channel: string, data: any) => void, headers?: any): number
|
|
1339
|
+
websocketSend(id: number, message: string | ArrayBuffer): void
|
|
1340
|
+
websocketClose(id: number): void
|
|
1341
|
+
|
|
1342
|
+
// ---- Service channel (headless registerService capabilities) --------------------------------
|
|
1343
|
+
// The UI-less sibling of the NativeView channel (docs/service-channel-plan.md): the host
|
|
1344
|
+
// registers named service factories (`registerService("geolocation", factory)`) and the SDK
|
|
1345
|
+
// talks to them over the same JSON call/event protocol as viewCall. All four are optional —
|
|
1346
|
+
// feature-detect with typeof; hosts that didn't opt in simply don't have them. Sessions must
|
|
1347
|
+
// open cheaply (no permission prompt, no I/O) — prompts belong in the first call that needs
|
|
1348
|
+
// them, so a rejected call is the failure surface, never a hung open.
|
|
1349
|
+
isServiceSupported?(name: string): boolean
|
|
1350
|
+
/** Open a session against the registered factory. `params` is a JSON string. Returns the
|
|
1351
|
+
* host-allocated session id, or -1 when no factory is registered under `name`. `onEvent`
|
|
1352
|
+
* delivers service events (payload as a JSON string, or omitted) until serviceClose. */
|
|
1353
|
+
serviceOpen?(name: string, params: string, onEvent: (event: string, dataJson?: string) => void): number
|
|
1354
|
+
/** Invoke a method on a live session — args/result JSON-encoded, exactly like viewCall. */
|
|
1355
|
+
serviceCall?(serviceId: number, method: string, args: string,
|
|
1356
|
+
onComplete: (result?: string) => void, onError: (err: string) => void): void
|
|
1357
|
+
serviceClose?(serviceId: number): void
|
|
1358
|
+
|
|
1359
|
+
// ---- App lifecycle & environment (docs/app-lifecycle-plan.md) --------------------------------
|
|
1360
|
+
// One push channel + synchronous pulls. All optional — typeof feature-detect; the SDK wrappers
|
|
1361
|
+
// fall back cleanly (state "active", launchUrl null, online true) on hosts that lack them.
|
|
1362
|
+
/** Register THE app-event listener (single slot per JS world — the SDK fans out; the host/core
|
|
1363
|
+
* scopes the stored callback to the world and frees it on teardown). Events: "pause" / "resume"
|
|
1364
|
+
* (app left / returned to the foreground), "url" (a link arrived while running; data = the URL),
|
|
1365
|
+
* "online" / "offline" (connectivity changed). "pause" is delivered BEFORE the host halts the
|
|
1366
|
+
* frame loop (the dispatch queue must still drain). */
|
|
1367
|
+
registerAppEvent?(callback: (event: string, data?: string) => void): void
|
|
1368
|
+
/** Current lifecycle state: "active" | "background". Surfaced as app.state. */
|
|
1369
|
+
appState?(): string
|
|
1370
|
+
/** The URL the app was (most recently) opened with, or null — the cold-start deep link. A warm
|
|
1371
|
+
* link updates this value first, then fires the "url" event. Surfaced as app.launchUrl. */
|
|
1372
|
+
getLaunchUrl?(): string | null
|
|
1373
|
+
/** Current connectivity (navigator.onLine semantics — best-effort: false only when the platform
|
|
1374
|
+
* is sure there is no network). Surfaced as device.online. */
|
|
1375
|
+
isOnline?(): boolean
|
|
1376
|
+
/** Open a URL in the system browser / external handler (fire-and-forget). Backs openURL(). */
|
|
1377
|
+
openUrl?(url: string): void
|
|
1378
|
+
/** Lock the interface orientation: "landscape" (either landscape direction — sensor
|
|
1379
|
+
* landscape, what a horizontal game wants), "portrait" (upright only) or "auto" (release —
|
|
1380
|
+
* the device's rotation rules apply again). Fire-and-forget; the rotation itself is
|
|
1381
|
+
* animated by the platform and lands as an ordinary resize. PER WORLD: the host resets the
|
|
1382
|
+
* lock to "auto" on every world swap BEFORE the new bundle evaluates, so a game may lock at
|
|
1383
|
+
* synchronous top level and the launcher always comes back unlocked. Optional — hosts
|
|
1384
|
+
* without a rotatable screen (desktop, headless, macOS) omit it. Backs app.setOrientation. */
|
|
1385
|
+
setOrientation?(mode: string): void
|
|
1386
|
+
/** Write text to the system clipboard (fire-and-forget). Backs clipboard.write. */
|
|
1387
|
+
clipboardWrite?(text: string): void
|
|
1388
|
+
/** Read text from the system clipboard — async because web needs a permission prompt; native
|
|
1389
|
+
* hosts may complete synchronously. Reject = no access / nothing readable. Backs clipboard.read. */
|
|
1390
|
+
clipboardRead?(onComplete: (text: string) => void, onReject: (err: string) => void): void
|
|
1391
|
+
|
|
1392
|
+
// ---- Keyboard inset (docs/input-upgrades-plan.md §7) ------------------------------------------
|
|
1393
|
+
/** On-screen keyboard height in logical px currently overlapping the app viewport, 0 when
|
|
1394
|
+
* hidden. The RAW overlap, independent of the focused input's keyboardShrink policy (with
|
|
1395
|
+
* shrink the layout already avoids it; the main consumer is overlay mode). Surfaced as
|
|
1396
|
+
* app.keyboardHeight. Optional — hosts without an on-screen keyboard omit it. */
|
|
1397
|
+
keyboardHeight?(): number
|
|
1398
|
+
/** Register THE keyboard listener (single slot per JS world, like registerAppEvent — the SDK
|
|
1399
|
+
* fans out; a separate channel because the string one can't carry two numbers). Fires on every
|
|
1400
|
+
* keyboard frame change with (height — as above, duration — the platform's animation duration
|
|
1401
|
+
* in ms, 0 where none). Surfaced as the app "keyboard" event. */
|
|
1402
|
+
registerKeyboardEvent?(callback: (height: number, duration: number) => void): void
|
|
1403
|
+
|
|
1404
|
+
// (camera* removed 2026-07-15 — CameraView rides the registered "camera" NativeView; hosts
|
|
1405
|
+
// keep the old handlers only for previously compiled bundles.)
|
|
1406
|
+
|
|
1407
|
+
createAudioPlayer(src: string, onFinished: () => void): number
|
|
1408
|
+
createVideoPlayer(src: string, onFinished: () => void): number
|
|
1409
|
+
updateMediaPlayerVolume(id: number, volume: number): void
|
|
1410
|
+
updateMediaPlayerLoop(id: number, loop: boolean): void
|
|
1411
|
+
updateMediaPlayerPlaying(id: number, play: boolean): void
|
|
1412
|
+
getMediaPlayerTime(id: number): number
|
|
1413
|
+
setMediaPlayerTime(id: number, time: number): void
|
|
1414
|
+
getMediaPlayerDuration(id: number): number
|
|
1415
|
+
removeMediaPlayer(id: number): void
|
|
1416
|
+
|
|
1417
|
+
/** The host bucket surfaced as `device.platform`. Apps BRANCH on it (mouse-look vs on-screen
|
|
1418
|
+
* sticks, hover affordances, key hints), so it names the INPUT MODEL, not the OS — one of
|
|
1419
|
+
* "web" | "ios" | "android" | "desktop". macOS reports "desktop", not "macos": a project
|
|
1420
|
+
* testing `device.platform === "desktop"` must get the same answer on every desktop host.
|
|
1421
|
+
* OS/version detail belongs in the host's own systemInfo callback, never here. Every host
|
|
1422
|
+
* must define it — where it was missing (Android before 2026-07-30, iOS before 2026-08-25)
|
|
1423
|
+
* the SDK read undefined and no platform branch in any app could ever match. */
|
|
1424
|
+
platform: string
|
|
1425
|
+
language: string
|
|
1426
|
+
/** Display device-pixel ratio (physical px per CSS/logical px): 1 on standard displays, 2–3 on
|
|
1427
|
+
* retina / iOS. Host-provided (web: window.devicePixelRatio; iOS: UIScreen.scale). Surfaced as
|
|
1428
|
+
* device.pixelRatio — for baking a Canvas at the right resolution without hardcoding it. */
|
|
1429
|
+
pixelRatio: number
|
|
1430
|
+
/** Opt into the precise-touch system (full-rate coalesced sampling) where the host supports it — iOS
|
|
1431
|
+
* coalesced touches. Surfaced as device.setPreciseTouch. Optional: hosts without a coalesced-input
|
|
1432
|
+
* concept (web, headless) simply don't implement it, so callers guard with `?.`. */
|
|
1433
|
+
setPreciseTouch?(enabled: boolean): void
|
|
1434
|
+
/** Fire a one-shot semantic haptic (device.vibrate). `style` is a HapticStyle string. Optional:
|
|
1435
|
+
* hosts without haptic hardware (web, headless, iPad / older iPhones) simply don't implement it,
|
|
1436
|
+
* so callers guard with `?.`. */
|
|
1437
|
+
vibrate?(style: string): void
|
|
1438
|
+
|
|
1439
|
+
// ---- device.motion (orientation sensor; pull-per-frame model) --------------------------------
|
|
1440
|
+
/** Does this device have the motion sensors (gyro)? Surfaced as device.motion.available. */
|
|
1441
|
+
motionAvailable?(): boolean
|
|
1442
|
+
/** Start fused device-motion updates at `interval` seconds; returns whether it started (false =
|
|
1443
|
+
* no sensor / permission denied). May return a Promise on hosts with an async permission prompt
|
|
1444
|
+
* (web). Surfaced as device.motion.start. */
|
|
1445
|
+
motionStart?(interval: number): boolean | Promise<boolean>
|
|
1446
|
+
/** Stop updates and release the sensor. Surfaced as device.motion.stop. */
|
|
1447
|
+
motionStop?(): void
|
|
1448
|
+
/** The freshest raw sample in the DEVICE frame: `[qx,qy,qz,qw, gx,gy,gz, interfaceOrientation]`
|
|
1449
|
+
* (orientation code: 0 portrait, 1 landscapeLeft, 2 landscapeRight, 3 upsideDown), or null until
|
|
1450
|
+
* the first sample / when not running. The SDK converts it to world/screen space. */
|
|
1451
|
+
getMotionSample?(): number[] | null
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// ---- 2D canvas (core; native-per-platform — see docs/canvas-contract.md) ---------------------
|
|
1455
|
+
// Immediate-mode 2D drawing that bakes to a texture, shared by 2D/3D/UI. The SDK Canvas records a
|
|
1456
|
+
// command buffer and flushes it here once per bake (opcodes documented in the contract).
|
|
1457
|
+
var _creatorCanvas: {
|
|
1458
|
+
// Rasterize `cmd` (cmdLen floats) into surface `surfaceId` (0 = create), sized w×h logical @
|
|
1459
|
+
// `scale` device px. Clears then replays the whole buffer. Returns the surface id.
|
|
1460
|
+
rasterize(surfaceId: number, w: number, h: number, scale: number,
|
|
1461
|
+
cmd: Float32Array, cmdLen: number, refs: string[]): number
|
|
1462
|
+
// [width, ascent, descent] in logical px for `text` in `font`, measured on this platform.
|
|
1463
|
+
measureText(text: string, font: string): Float32Array
|
|
1464
|
+
// Copy surface `surfaceId`'s pixels into a NEW standalone surface; returns the new id. Backs
|
|
1465
|
+
// Canvas.toBitmap() — an immutable snapshot the source canvas can no longer touch.
|
|
1466
|
+
snapshot(surfaceId: number): number
|
|
1467
|
+
// Decode an image source into a NEW standalone surface (device px) — backs Canvas.loadImage() for
|
|
1468
|
+
// Canvas.drawImage(). `bufferId < 0` → rasterize the SVG markup in `svg`; otherwise decode the
|
|
1469
|
+
// encoded image bytes in host buffer `bufferId` (an already-fetched FetchResponse). Async, because
|
|
1470
|
+
// turning SVG / encoded bytes into pixels needs a decode on web (createImageBitmap / <img>). Returns
|
|
1471
|
+
// (surfaceId, width, height) in device px via onComplete, or onReject on failure.
|
|
1472
|
+
loadImage(svg: string, bufferId: number,
|
|
1473
|
+
onComplete: (surfaceId: number, width: number, height: number) => void, onReject: () => void): void
|
|
1474
|
+
// Encode surface `surfaceId` to an image ('image/png' | 'image/jpeg'), register the bytes as a host
|
|
1475
|
+
// buffer, and return (bufferId, size) — the SDK wraps it in a File. Backs Canvas/Bitmap.toFile().
|
|
1476
|
+
toFile(surfaceId: number, type: string, onComplete: (bufferId: number, size: number) => void, onReject: () => void): void
|
|
1477
|
+
destroySurface(surfaceId: number): void
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
export {}
|