@defold-typescript/types 0.50.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api-signatures.json +286 -232
- package/examples/translations.json +15 -15
- package/fixtures/messages_doc.json +20 -39
- package/generated/builtin-messages.d.ts +16 -14
- package/generated/collectionfactory.d.ts +1 -1
- package/generated/collectionproxy.d.ts +2 -2
- package/generated/factory.d.ts +4 -2
- package/generated/graphics.d.ts +4 -0
- package/generated/gui.d.ts +2 -2
- package/generated/http.d.ts +3 -1
- package/generated/image.d.ts +1 -1
- package/generated/kinds/gui-script.d.ts +1 -0
- package/generated/kinds/render-script.d.ts +1 -0
- package/generated/kinds/script.d.ts +1 -0
- package/generated/model.d.ts +4 -5
- package/generated/physics.d.ts +3 -3
- package/generated/render.d.ts +41 -13
- package/generated/sys.d.ts +8 -4
- package/generated/tilemap.d.ts +4 -4
- package/generated/versions/defold-1.12.4/collectionfactory.d.ts +1 -1
- package/generated/versions/defold-1.12.4/collectionproxy.d.ts +1 -1
- package/generated/versions/defold-1.12.4/factory.d.ts +4 -2
- package/generated/versions/defold-1.12.4/gui.d.ts +2 -2
- package/generated/versions/defold-1.12.4/http.d.ts +3 -1
- package/generated/versions/defold-1.12.4/image.d.ts +1 -1
- package/generated/versions/defold-1.12.4/index.d.ts +1 -0
- package/generated/versions/defold-1.12.4/model.d.ts +4 -5
- package/generated/versions/defold-1.12.4/physics.d.ts +2 -2
- package/generated/versions/defold-1.12.4/render.d.ts +41 -13
- package/generated/versions/defold-1.12.4/sys.d.ts +1 -1
- package/generated/versions/defold-1.12.4/tilemap.d.ts +4 -4
- package/generated/versions/defold-1.13.0/collectionfactory.d.ts +1 -1
- package/generated/versions/defold-1.13.0/collectionproxy.d.ts +1 -1
- package/generated/versions/defold-1.13.0/factory.d.ts +4 -2
- package/generated/versions/defold-1.13.0/gui.d.ts +2 -2
- package/generated/versions/defold-1.13.0/http.d.ts +3 -1
- package/generated/versions/defold-1.13.0/image.d.ts +1 -1
- package/generated/versions/defold-1.13.0/index.d.ts +1 -0
- package/generated/versions/defold-1.13.0/model.d.ts +4 -5
- package/generated/versions/defold-1.13.0/physics.d.ts +2 -2
- package/generated/versions/defold-1.13.0/render.d.ts +41 -13
- package/generated/versions/defold-1.13.0/sys.d.ts +1 -1
- package/generated/versions/defold-1.13.0/tilemap.d.ts +4 -4
- package/generated/versions/defold-1.13.1/collectionfactory.d.ts +1 -1
- package/generated/versions/defold-1.13.1/collectionproxy.d.ts +1 -1
- package/generated/versions/defold-1.13.1/factory.d.ts +4 -2
- package/generated/versions/defold-1.13.1/gui.d.ts +2 -2
- package/generated/versions/defold-1.13.1/http.d.ts +3 -1
- package/generated/versions/defold-1.13.1/image.d.ts +1 -1
- package/generated/versions/defold-1.13.1/index.d.ts +1 -0
- package/generated/versions/defold-1.13.1/model.d.ts +4 -5
- package/generated/versions/defold-1.13.1/physics.d.ts +2 -2
- package/generated/versions/defold-1.13.1/render.d.ts +41 -13
- package/generated/versions/defold-1.13.1/sys.d.ts +1 -1
- package/generated/versions/defold-1.13.1/tilemap.d.ts +4 -4
- package/generated/versions/defold-1.13.2/collectionfactory.d.ts +1 -1
- package/generated/versions/defold-1.13.2/collectionproxy.d.ts +2 -2
- package/generated/versions/defold-1.13.2/factory.d.ts +4 -2
- package/generated/versions/defold-1.13.2/gui.d.ts +2 -2
- package/generated/versions/defold-1.13.2/http.d.ts +3 -1
- package/generated/versions/defold-1.13.2/image.d.ts +1 -1
- package/generated/versions/defold-1.13.2/index.d.ts +1 -0
- package/generated/versions/defold-1.13.2/model.d.ts +4 -5
- package/generated/versions/defold-1.13.2/physics.d.ts +3 -3
- package/generated/versions/defold-1.13.2/render.d.ts +41 -13
- package/generated/versions/defold-1.13.2/sys.d.ts +8 -4
- package/generated/versions/defold-1.13.2/tilemap.d.ts +4 -4
- package/generated/versions/defold-1.13.2/window.d.ts +1 -1
- package/generated/window.d.ts +1 -1
- package/identity-vocabulary.json +46 -0
- package/index.d.ts +1 -0
- package/package.json +2 -1
- package/scripts/generate-api-availability.ts +5 -1
- package/scripts/generate-api-signatures.ts +16 -11
- package/scripts/materialize-version.ts +7 -1
- package/scripts/regen.ts +42 -25
- package/src/component-properties.d.ts +137 -6
- package/src/core-types.ts +46 -11
- package/src/emit-dts.ts +555 -84
- package/src/emit-messages.ts +289 -0
- package/src/engine-globals.d.ts +3 -1
- package/src/go-overloads.d.ts +13 -3
- package/src/lifecycle.ts +16 -16
- package/src/luals-type-expr.ts +6 -1
- package/src/physics-event-guard.d.ts +39 -0
- package/src/render-overloads.d.ts +2 -2
- package/src/return-correction-provenance.ts +36 -6
- package/src/window-event-guard.d.ts +5 -3
package/src/emit-messages.ts
CHANGED
|
@@ -137,6 +137,295 @@ export function applyMessageFieldCorrections(
|
|
|
137
137
|
return { entries };
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
// What only the engine states about a message the catalog mirrors from the
|
|
141
|
+
// reference: proto optionality, a field the handler reads or the sender fills,
|
|
142
|
+
// a message a component handles or posts, or the shape of a field the reference
|
|
143
|
+
// types only as `table`. `evidence` names `<path>:<symbol>` in the 1.14.0 engine
|
|
144
|
+
// source. Each kind throws once the catalog already states its fact, since that
|
|
145
|
+
// means upstream fixed the reference and the entry is deleted; a `retype` throws
|
|
146
|
+
// once the catalog stops declaring its pinned `upstream` types, since upstream
|
|
147
|
+
// retyped the field and the entry is re-verified against what it now says.
|
|
148
|
+
export type MessageEngineCorrection = {
|
|
149
|
+
readonly origin: string;
|
|
150
|
+
readonly name: string;
|
|
151
|
+
readonly evidence: string;
|
|
152
|
+
} & (
|
|
153
|
+
| { readonly kind: "optional" | "required"; readonly fields: readonly string[] }
|
|
154
|
+
| { readonly kind: "add-field"; readonly fields: readonly MessageField[] }
|
|
155
|
+
| {
|
|
156
|
+
readonly kind: "add-message";
|
|
157
|
+
readonly description: string;
|
|
158
|
+
readonly fields: readonly MessageField[];
|
|
159
|
+
}
|
|
160
|
+
| {
|
|
161
|
+
readonly kind: "retype";
|
|
162
|
+
readonly fields: readonly string[];
|
|
163
|
+
readonly tsType: string;
|
|
164
|
+
readonly upstream: readonly string[];
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const SCRIPT_DDF_DEFAULTS =
|
|
169
|
+
"script/src/script_ddf.cpp:DoLuaTableToDDF fills an omitted optional field with its default";
|
|
170
|
+
const SOUND_EVENT =
|
|
171
|
+
"gamesys/src/gamesys/components/comp_sound.cpp:DispatchSoundEvent always sets play_id, and HandleEntryFinishedPlaying sends the event only for a play_sound that supplied one";
|
|
172
|
+
|
|
173
|
+
function optionalField(name: string, types: string[], doc: string): MessageField {
|
|
174
|
+
return { name, types, optional: true, doc };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function requiredField(name: string, types: string[], doc: string): MessageField {
|
|
178
|
+
return { name, types, optional: false, doc };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// The listener and `on_message` paths agree: the DDF the message carries
|
|
182
|
+
// declares the same sub-message fields the listener push sets.
|
|
183
|
+
function physicsBody(message: string): string {
|
|
184
|
+
return `gamesys/proto/gamesys/physics_ddf.proto:${message} declares the same required fields for the on_message payload`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function otherGroupField(): MessageField {
|
|
188
|
+
return {
|
|
189
|
+
name: "group",
|
|
190
|
+
types: ["hash"],
|
|
191
|
+
optional: false,
|
|
192
|
+
doc: "Collision group of the other object, equal to other_group.",
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const MESSAGE_ENGINE_CORRECTIONS: readonly MessageEngineCorrection[] = [
|
|
197
|
+
{
|
|
198
|
+
kind: "optional",
|
|
199
|
+
origin: "camera",
|
|
200
|
+
name: "set_camera",
|
|
201
|
+
fields: ["orthographic_projection", "orthographic_zoom", "orthographic_mode"],
|
|
202
|
+
evidence: `gamesys/proto/gamesys/camera_ddf.proto:SetCamera declares them optional with defaults, CompCameraOnMessage handles it, and ${SCRIPT_DDF_DEFAULTS}`,
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
kind: "optional",
|
|
206
|
+
origin: "sys",
|
|
207
|
+
name: "reboot",
|
|
208
|
+
fields: ["arg1", "arg2", "arg3", "arg4", "arg5", "arg6"],
|
|
209
|
+
evidence: `script/src/script/sys_ddf.proto:Reboot declares every argument optional, engine/src/engine.cpp:Dispatch handles it, and ${SCRIPT_DDF_DEFAULTS}`,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
kind: "optional",
|
|
213
|
+
origin: "sys",
|
|
214
|
+
name: "start_record",
|
|
215
|
+
fields: ["frame_period", "fps"],
|
|
216
|
+
evidence: `script/src/script/sys_ddf.proto:StartRecord declares both optional with defaults 2 and 30, engine/src/engine.cpp:Dispatch handles it, and ${SCRIPT_DDF_DEFAULTS}`,
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
kind: "optional",
|
|
220
|
+
origin: "sprite",
|
|
221
|
+
name: "play_animation",
|
|
222
|
+
fields: ["offset", "playback_rate"],
|
|
223
|
+
evidence: `gamesys/proto/gamesys/sprite_ddf.proto:PlayAnimation declares both optional with defaults 0 and 1, comp_sprite.cpp:CompSpriteOnMessage passes both to PlayAnimation, and ${SCRIPT_DDF_DEFAULTS}`,
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
kind: "optional",
|
|
227
|
+
origin: "go",
|
|
228
|
+
name: "set_parent",
|
|
229
|
+
fields: ["parent_id", "keep_world_transform"],
|
|
230
|
+
evidence: `gameobject/proto/gameobject/gameobject_ddf.proto:SetParent declares both optional with defaults 0 and 1, gameobject.cpp:DispatchMessagesFunction handles it, and ${SCRIPT_DDF_DEFAULTS}`,
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
kind: "required",
|
|
234
|
+
origin: "sound",
|
|
235
|
+
name: "sound_done",
|
|
236
|
+
fields: ["play_id"],
|
|
237
|
+
evidence: SOUND_EVENT,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
kind: "required",
|
|
241
|
+
origin: "sound",
|
|
242
|
+
name: "sound_stopped",
|
|
243
|
+
fields: ["play_id"],
|
|
244
|
+
evidence: SOUND_EVENT,
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
kind: "add-field",
|
|
248
|
+
origin: "sound",
|
|
249
|
+
name: "play_sound",
|
|
250
|
+
fields: [
|
|
251
|
+
optionalField("pan", ["number"], "Pan between -1 and 1, added to the component's pan."),
|
|
252
|
+
optionalField("speed", ["number"], "Speed factor, multiplied with the component's speed."),
|
|
253
|
+
],
|
|
254
|
+
evidence:
|
|
255
|
+
"gamesys/proto/gamesys/gamesys_ddf.proto:PlaySound declares pan and speed, and comp_sound.cpp:CompSoundOnMessage applies both to the voice",
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
kind: "add-field",
|
|
259
|
+
origin: "sound",
|
|
260
|
+
name: "stop_sound",
|
|
261
|
+
fields: [
|
|
262
|
+
optionalField(
|
|
263
|
+
"play_id",
|
|
264
|
+
["number"],
|
|
265
|
+
"Id passed to play_sound; stops only that voice. Omit to stop every voice.",
|
|
266
|
+
),
|
|
267
|
+
],
|
|
268
|
+
evidence:
|
|
269
|
+
"gamesys/proto/gamesys/gamesys_ddf.proto:StopSound declares play_id, and comp_sound.cpp:CompSoundOnMessage stops only the voice that matches it",
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
kind: "add-message",
|
|
273
|
+
origin: "sound",
|
|
274
|
+
name: "pause_sound",
|
|
275
|
+
description: "Pause or resume every voice the receiving sound component plays.",
|
|
276
|
+
fields: [optionalField("pause", ["boolean"], "true (default) to pause, false to resume.")],
|
|
277
|
+
evidence:
|
|
278
|
+
"gamesys/proto/gamesys/gamesys_ddf.proto:PauseSound declares pause, and comp_sound.cpp:CompSoundOnMessage pauses every voice of the component",
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
kind: "add-message",
|
|
282
|
+
origin: "sound",
|
|
283
|
+
name: "set_pan",
|
|
284
|
+
description: "Set the pan on the receiving sound component.",
|
|
285
|
+
fields: [optionalField("pan", ["number"], "Pan between -1 and 1, default 0.")],
|
|
286
|
+
evidence:
|
|
287
|
+
"gamesys/proto/gamesys/gamesys_ddf.proto:SetPan declares pan, and comp_sound.cpp:CompSoundOnMessage sets the component's pan",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
kind: "add-message",
|
|
291
|
+
origin: "render",
|
|
292
|
+
name: "set_view_projection",
|
|
293
|
+
description:
|
|
294
|
+
"Posted automatically by camera components to the render script with the active view and projection matrices.",
|
|
295
|
+
fields: [
|
|
296
|
+
requiredField("id", ["hash"], "Id of the camera component that posted the matrices."),
|
|
297
|
+
requiredField("view", ["matrix4"], "View matrix of the camera."),
|
|
298
|
+
requiredField("projection", ["matrix4"], "Projection matrix of the camera."),
|
|
299
|
+
],
|
|
300
|
+
evidence:
|
|
301
|
+
"gamesys/proto/gamesys/gamesys_ddf.proto:SetViewProjection declares id, view and projection required, and comp_camera.cpp:PostRenderScriptSetViewProjectionMsg posts it to the render socket on every camera update",
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
kind: "add-field",
|
|
305
|
+
origin: "physics",
|
|
306
|
+
name: "collision_response",
|
|
307
|
+
fields: [otherGroupField()],
|
|
308
|
+
evidence:
|
|
309
|
+
"gamesys/proto/gamesys/physics_ddf.proto:CollisionResponse declares a required group, and comp_collision_object.cpp:CollisionCallback sets it to the other object's group",
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
kind: "add-field",
|
|
313
|
+
origin: "physics",
|
|
314
|
+
name: "contact_point_response",
|
|
315
|
+
fields: [otherGroupField()],
|
|
316
|
+
evidence:
|
|
317
|
+
"gamesys/proto/gamesys/physics_ddf.proto:ContactPointResponse declares a required group, and comp_collision_object.cpp:ContactPointCallback sets it to the other object's group",
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
kind: "add-field",
|
|
321
|
+
origin: "physics",
|
|
322
|
+
name: "trigger_response",
|
|
323
|
+
fields: [otherGroupField()],
|
|
324
|
+
evidence:
|
|
325
|
+
"gamesys/proto/gamesys/physics_ddf.proto:TriggerResponse declares a required group, and comp_collision_object.cpp:TriggerEnteredCallback sets it to the other object's group",
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
kind: "retype",
|
|
329
|
+
origin: "physics",
|
|
330
|
+
name: "contact_point_event",
|
|
331
|
+
fields: ["a", "b"],
|
|
332
|
+
tsType:
|
|
333
|
+
"{ position: Vector3; instance_position: Vector3; normal: Vector3; relative_velocity: Vector3; mass: number; id: Hash; group: Hash }",
|
|
334
|
+
upstream: ["table"],
|
|
335
|
+
evidence: `gamesys/src/gamesys/scripts/script_physics.cpp:PushContactPoint sets these seven fields on each body, and ${physicsBody("ContactPoint")}`,
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
kind: "retype",
|
|
339
|
+
origin: "physics",
|
|
340
|
+
name: "collision_event",
|
|
341
|
+
fields: ["a", "b"],
|
|
342
|
+
tsType: "{ position: Vector3; id: Hash; group: Hash }",
|
|
343
|
+
upstream: ["table"],
|
|
344
|
+
evidence: `gamesys/src/gamesys/scripts/script_physics.cpp:PushCollision sets these three fields on each body, and ${physicsBody("Collision")}`,
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
kind: "retype",
|
|
348
|
+
origin: "physics",
|
|
349
|
+
name: "trigger_event",
|
|
350
|
+
fields: ["a", "b"],
|
|
351
|
+
tsType: "{ id: Hash; group: Hash }",
|
|
352
|
+
upstream: ["table"],
|
|
353
|
+
evidence: `gamesys/src/gamesys/scripts/script_physics.cpp:PushTrigger sets these two fields on each body, and ${physicsBody("Trigger")}`,
|
|
354
|
+
},
|
|
355
|
+
];
|
|
356
|
+
|
|
357
|
+
export function applyMessageEngineCorrections(
|
|
358
|
+
catalog: MessageCatalog,
|
|
359
|
+
overlay: readonly MessageEngineCorrection[] = MESSAGE_ENGINE_CORRECTIONS,
|
|
360
|
+
): MessageCatalog {
|
|
361
|
+
const entries = catalog.entries.map((entry) => ({
|
|
362
|
+
...entry,
|
|
363
|
+
payload: entry.payload.map((field) => ({ ...field })),
|
|
364
|
+
}));
|
|
365
|
+
for (const correction of overlay) {
|
|
366
|
+
const identity = `(origin=${correction.origin}, name=${correction.name})`;
|
|
367
|
+
const stale = (fact: string) =>
|
|
368
|
+
new Error(
|
|
369
|
+
`applyMessageEngineCorrections: the catalog ${fact} for ${identity}; delete the correction`,
|
|
370
|
+
);
|
|
371
|
+
const entry = entries.find(
|
|
372
|
+
(candidate) => candidate.origin === correction.origin && candidate.name === correction.name,
|
|
373
|
+
);
|
|
374
|
+
if (correction.kind === "add-message") {
|
|
375
|
+
if (entry) throw stale("already declares message");
|
|
376
|
+
entries.push({
|
|
377
|
+
name: correction.name,
|
|
378
|
+
origin: correction.origin,
|
|
379
|
+
description: correction.description,
|
|
380
|
+
payload: correction.fields.map((field) => ({ ...field, types: [...field.types] })),
|
|
381
|
+
});
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (!entry) {
|
|
385
|
+
throw new Error(`applyMessageEngineCorrections: no catalog message matches ${identity}`);
|
|
386
|
+
}
|
|
387
|
+
if (correction.kind === "add-field") {
|
|
388
|
+
for (const field of correction.fields) {
|
|
389
|
+
if (entry.payload.some((candidate) => candidate.name === field.name)) {
|
|
390
|
+
throw stale(`already declares field ${field.name}`);
|
|
391
|
+
}
|
|
392
|
+
entry.payload.push({ ...field, types: [...field.types] });
|
|
393
|
+
}
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
for (const name of correction.fields) {
|
|
397
|
+
const field = entry.payload.find((candidate) => candidate.name === name);
|
|
398
|
+
if (!field) {
|
|
399
|
+
throw new Error(
|
|
400
|
+
`applyMessageEngineCorrections: no catalog field matches ${identity} field=${name}`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
if (correction.kind === "retype") {
|
|
404
|
+
if (field.types.join("|") !== correction.upstream.join("|")) {
|
|
405
|
+
throw new Error(
|
|
406
|
+
`applyMessageEngineCorrections: the catalog now declares ${field.types.join("|")} for field ${name} of ${identity}, not the pinned ${correction.upstream.join("|")}; re-verify the correction`,
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
field.types = [correction.tsType];
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const optional = correction.kind === "optional";
|
|
413
|
+
if (field.optional === optional) throw stale(`field ${name} is already ${correction.kind}`);
|
|
414
|
+
field.optional = optional;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return { entries };
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// The built-in message surface is the catalog plus these overlays. Every reader
|
|
421
|
+
// of it goes through here, so a message the engine overlay adds is never missing
|
|
422
|
+
// from one of them.
|
|
423
|
+
export function applyMessageOverlays(catalog: MessageCatalog): MessageCatalog {
|
|
424
|
+
return applyMessageEngineCorrections(
|
|
425
|
+
applyMessageFieldCorrections(applyMessageDeprecations(catalog)),
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
140
429
|
const TS_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
141
430
|
const ENGINE_TYPES = [
|
|
142
431
|
"Hash",
|
package/src/engine-globals.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ declare global {
|
|
|
36
36
|
type Opaque<Name extends string> = Core.Opaque<Name>;
|
|
37
37
|
/** A message-passing address with `socket`, `path`, and `fragment`; see {@link Core.Url}. */
|
|
38
38
|
type Url = Core.Url;
|
|
39
|
-
/** A
|
|
39
|
+
/** A numeric vector read and written by 1-based index; see {@link Core.Vector}. */
|
|
40
40
|
type Vector = Core.Vector;
|
|
41
41
|
/** A three-component vector with `x`, `y`, `z`; see {@link Core.Vector3}. */
|
|
42
42
|
type Vector3 = Core.Vector3;
|
|
@@ -46,4 +46,6 @@ declare global {
|
|
|
46
46
|
type Quaternion = Core.Quaternion;
|
|
47
47
|
/** A 4x4 transformation matrix; see {@link Core.Matrix4}. */
|
|
48
48
|
type Matrix4 = Core.Matrix4;
|
|
49
|
+
/** An array constant read back from a constant buffer, 1-based with no length; see {@link Core.ConstantArray}. */
|
|
50
|
+
type ConstantArray<T> = Core.ConstantArray<T>;
|
|
49
51
|
}
|
package/src/go-overloads.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @noSelfInFile */
|
|
2
2
|
|
|
3
|
-
import type { Hash, Quaternion, Url, Vector3, Vector4 } from "./core-types";
|
|
3
|
+
import type { Hash, Matrix4, Quaternion, Url, Vector3, Vector4 } from "./core-types";
|
|
4
4
|
|
|
5
5
|
interface ScriptProperty<TValue> {
|
|
6
6
|
readonly __defoldScriptProperty: TValue;
|
|
@@ -61,7 +61,7 @@ declare global {
|
|
|
61
61
|
url: SceneAddress | Hash | Url,
|
|
62
62
|
property: string | Hash,
|
|
63
63
|
options?: GoPropertyOptions,
|
|
64
|
-
): number | boolean | string | Hash | Url | Vector3 | Vector4 | Quaternion;
|
|
64
|
+
): number | boolean | string | Hash | Url | Vector3 | Vector4 | Quaternion | Matrix4;
|
|
65
65
|
/**
|
|
66
66
|
* sets a named property of the specified game object or component, or a material constant
|
|
67
67
|
*
|
|
@@ -97,7 +97,17 @@ declare global {
|
|
|
97
97
|
function set(
|
|
98
98
|
url: SceneAddress | Hash | Url,
|
|
99
99
|
property: string | Hash,
|
|
100
|
-
value:
|
|
100
|
+
value:
|
|
101
|
+
| number
|
|
102
|
+
| boolean
|
|
103
|
+
| string
|
|
104
|
+
| Hash
|
|
105
|
+
| Url
|
|
106
|
+
| Vector3
|
|
107
|
+
| Vector4
|
|
108
|
+
| Quaternion
|
|
109
|
+
| Matrix4
|
|
110
|
+
| Vector4[],
|
|
101
111
|
options?: GoPropertyOptions,
|
|
102
112
|
): void;
|
|
103
113
|
/**
|
package/src/lifecycle.ts
CHANGED
|
@@ -7,51 +7,51 @@ export interface InputTouch {
|
|
|
7
7
|
/**
|
|
8
8
|
* Identifier for the touch during its lifetime.
|
|
9
9
|
*/
|
|
10
|
-
id
|
|
10
|
+
id: number;
|
|
11
11
|
/**
|
|
12
12
|
* Whether the finger was pressed this frame.
|
|
13
13
|
*/
|
|
14
|
-
pressed
|
|
14
|
+
pressed: boolean;
|
|
15
15
|
/**
|
|
16
16
|
* Whether the finger was released this frame.
|
|
17
17
|
*/
|
|
18
|
-
released
|
|
18
|
+
released: boolean;
|
|
19
19
|
/**
|
|
20
20
|
* Number of taps, such as one for a single tap and two for a double tap.
|
|
21
21
|
*/
|
|
22
|
-
tap_count
|
|
22
|
+
tap_count: number;
|
|
23
23
|
/**
|
|
24
24
|
* Touch x-coordinate.
|
|
25
25
|
*/
|
|
26
|
-
x
|
|
26
|
+
x: number;
|
|
27
27
|
/**
|
|
28
28
|
* Touch y-coordinate.
|
|
29
29
|
*/
|
|
30
|
-
y
|
|
30
|
+
y: number;
|
|
31
31
|
/**
|
|
32
32
|
* Change in the touch x-coordinate.
|
|
33
33
|
*/
|
|
34
|
-
dx
|
|
34
|
+
dx: number;
|
|
35
35
|
/**
|
|
36
36
|
* Change in the touch y-coordinate.
|
|
37
37
|
*/
|
|
38
|
-
dy
|
|
38
|
+
dy: number;
|
|
39
39
|
/**
|
|
40
40
|
* Touch x-coordinate in screen space.
|
|
41
41
|
*/
|
|
42
|
-
screen_x
|
|
42
|
+
screen_x: number;
|
|
43
43
|
/**
|
|
44
44
|
* Touch y-coordinate in screen space.
|
|
45
45
|
*/
|
|
46
|
-
screen_y
|
|
46
|
+
screen_y: number;
|
|
47
47
|
/**
|
|
48
48
|
* Change in the touch x-coordinate in screen space.
|
|
49
49
|
*/
|
|
50
|
-
screen_dx
|
|
50
|
+
screen_dx: number;
|
|
51
51
|
/**
|
|
52
52
|
* Change in the touch y-coordinate in screen space.
|
|
53
53
|
*/
|
|
54
|
-
screen_dy
|
|
54
|
+
screen_dy: number;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// Fields and docs follow the go ref-doc's `on_input.action` STRUCT, whose keys are
|
|
@@ -363,7 +363,7 @@ export type GuiScriptHooks<TSelf, TInitState = TSelf> = Omit<
|
|
|
363
363
|
|
|
364
364
|
export type RenderScriptHooks<TSelf, TInitState = TSelf> = Omit<
|
|
365
365
|
ScriptHooks<TSelf, TInitState>,
|
|
366
|
-
"on_input"
|
|
366
|
+
"on_input" | "final" | "fixed_update" | "late_update"
|
|
367
367
|
>;
|
|
368
368
|
|
|
369
369
|
// The factory hook table plus the value-keyed `properties` field. `TProps` is
|
|
@@ -547,9 +547,9 @@ export function defineGuiScript<
|
|
|
547
547
|
* {@link defineScript}, and is erased by the transpiler's `lifecycle-erasure`
|
|
548
548
|
* pass into the flat Defold chunk shape.
|
|
549
549
|
*
|
|
550
|
-
* `RenderScriptHooks` is `Omit<ScriptHooks, "on_input"
|
|
551
|
-
*
|
|
552
|
-
*
|
|
550
|
+
* `RenderScriptHooks` is `Omit<ScriptHooks, "on_input" | "final" |
|
|
551
|
+
* "fixed_update" | "late_update">` — the engine calls only four render-script
|
|
552
|
+
* hooks, all optional: `init`, `update`, `on_message`, `on_reload`.
|
|
553
553
|
*
|
|
554
554
|
* Scaffold it with the `def-ts-defineRenderScript-inferred-self` / `def-ts-defineRenderScript-typed-self` VSCode snippets
|
|
555
555
|
* from `defold-typescript init`.
|
package/src/luals-type-expr.ts
CHANGED
|
@@ -334,6 +334,11 @@ export function mapLualsExpression(
|
|
|
334
334
|
return { ts: mapToken(token, walk), unknowns: walk.unknowns };
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
+
/** Whether a raw token is a typed LuaLS `fun(...)` expression rather than a bare `function(...)`. */
|
|
338
|
+
export function isLualsFunctionToken(token: string): boolean {
|
|
339
|
+
return /^fun\s*\(/.test(token.trim());
|
|
340
|
+
}
|
|
341
|
+
|
|
337
342
|
/**
|
|
338
343
|
* Map a `fun(...)` expression to a TypeScript **call signature** — the colon-return
|
|
339
344
|
* form `(params): ret` an interface uses to become callable, not the `=>` arrow a
|
|
@@ -345,7 +350,7 @@ export function mapLualsCallSignatureExpression(
|
|
|
345
350
|
position: LualsPosition = "output",
|
|
346
351
|
): LualsMapResult {
|
|
347
352
|
const trimmed = token.trim();
|
|
348
|
-
if (
|
|
353
|
+
if (!isLualsFunctionToken(trimmed)) {
|
|
349
354
|
throw new Error(`mapLualsCallSignature: expected a "fun(...)" token, got "${token}".`);
|
|
350
355
|
}
|
|
351
356
|
const walk: Walk = { resolveLeaf, unknowns: [], position };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** @noSelfInFile */
|
|
2
|
+
import type { Hash } from "./core-types";
|
|
3
|
+
|
|
4
|
+
// `physics.set_event_listener` sets `type` on every event to its message-name
|
|
5
|
+
// hash (script_physics.cpp), but a `Hash` is an object type, not a unit type, so
|
|
6
|
+
// an `event.type == hash("…")` check cannot narrow the event union. This guard
|
|
7
|
+
// re-introduces the literal at the use site. The transpiler lowers the call to
|
|
8
|
+
// `event.type == hash("…")` (physics-event-guard-lowering.ts), so this package
|
|
9
|
+
// emits no runtime Lua. It names no `physics` type, so it compiles on a surface
|
|
10
|
+
// whose reference declares no event union.
|
|
11
|
+
type PhysicsEventName<E> = E extends { type: Hash<infer N> } ? N : never;
|
|
12
|
+
|
|
13
|
+
declare global {
|
|
14
|
+
/**
|
|
15
|
+
* Type guard for a `physics.set_event_listener` callback: narrows one event
|
|
16
|
+
* to the member of the event union whose `type` is the hash of `name`. The
|
|
17
|
+
* engine sets `type` on every event, but a `Hash` cannot act as a union
|
|
18
|
+
* discriminant, so an `event.type == hash("collision_event")` check leaves the
|
|
19
|
+
* event unnarrowed — this guard re-introduces the literal.
|
|
20
|
+
*
|
|
21
|
+
* @param event - one entry of the `events` array the listener received.
|
|
22
|
+
* @param name - the event's message name (e.g. `"collision_event"`).
|
|
23
|
+
* @returns `true` when `event.type` is `hash(name)`, narrowing `event` to that event.
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* physics.set_event_listener((self, events) => {
|
|
27
|
+
* for (const event of events) {
|
|
28
|
+
* if (isPhysicsEvent(event, "collision_event")) {
|
|
29
|
+
* print(event.a.id, event.b.id);
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
function isPhysicsEvent<E extends { type: Hash }, K extends PhysicsEventName<E>>(
|
|
36
|
+
event: E,
|
|
37
|
+
name: K,
|
|
38
|
+
): event is Extract<E, { type: Hash<K> }>;
|
|
39
|
+
}
|
|
@@ -12,7 +12,7 @@ declare global {
|
|
|
12
12
|
* @param parameters - table of buffer parameters, see the description for available keys and values
|
|
13
13
|
* @returns new render target
|
|
14
14
|
*/
|
|
15
|
-
function render_target(parameters:
|
|
15
|
+
function render_target(parameters: render.RenderTargetParams): Opaque<"render_target">;
|
|
16
16
|
/**
|
|
17
17
|
* Creates a new named render target according to the supplied specification
|
|
18
18
|
* table. The name is used by the profiler and by render target lookups.
|
|
@@ -23,7 +23,7 @@ declare global {
|
|
|
23
23
|
*/
|
|
24
24
|
function render_target(
|
|
25
25
|
name: string,
|
|
26
|
-
parameters:
|
|
26
|
+
parameters: render.RenderTargetParams,
|
|
27
27
|
): Opaque<"render_target">;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -248,6 +248,10 @@ export interface ReturnTypeProvenance {
|
|
|
248
248
|
readonly sightedIn: readonly string[];
|
|
249
249
|
readonly neededBy: readonly string[];
|
|
250
250
|
readonly resolvedIn: readonly string[];
|
|
251
|
+
// Targets whose vendored binding does not show a binding-pinned entry's pin,
|
|
252
|
+
// so the emitter leaves the entry off there. Never a resolution: upstream
|
|
253
|
+
// documented nothing, the engine source changed.
|
|
254
|
+
readonly unboundIn: readonly string[];
|
|
251
255
|
readonly driftedIn: readonly string[];
|
|
252
256
|
readonly typeDrift: readonly string[];
|
|
253
257
|
}
|
|
@@ -255,14 +259,26 @@ export interface ReturnTypeProvenance {
|
|
|
255
259
|
// Same ranking argument as `FIELD_VERDICT_RANK`: `emitReturn` applies the
|
|
256
260
|
// correction to every declaration of the FQN in a target, so one drifted
|
|
257
261
|
// declaration makes that target's emit wrong whatever its siblings say.
|
|
258
|
-
|
|
262
|
+
// Binding evidence is per target, so for a binding-pinned entry `unbound` never
|
|
263
|
+
// meets another verdict in the same target.
|
|
264
|
+
type ReturnVerdict = "drift" | "needed" | "unbound" | "resolved";
|
|
259
265
|
|
|
260
266
|
const RETURN_VERDICT_RANK: Record<ReturnVerdict, number> = {
|
|
261
|
-
drift:
|
|
262
|
-
needed:
|
|
267
|
+
drift: 3,
|
|
268
|
+
needed: 2,
|
|
269
|
+
unbound: 1,
|
|
263
270
|
resolved: 0,
|
|
264
271
|
};
|
|
265
272
|
|
|
273
|
+
// Whether the declared tokens already say what the correction does. Tokens can
|
|
274
|
+
// state only the nil: a binding-pinned `ts` entry corrects what the binding sets
|
|
275
|
+
// (a field it never pushes), so upstream fixing that shows as a retype, which is
|
|
276
|
+
// drift, never as a resolution.
|
|
277
|
+
function declaresCorrection(tokens: readonly string[], correction: ReturnTypeCorrection): boolean {
|
|
278
|
+
if (correction.nullable === undefined && correction.binding !== undefined) return false;
|
|
279
|
+
return correction.nullable === false ? !tokens.includes("nil") : tokens.includes("nil");
|
|
280
|
+
}
|
|
281
|
+
|
|
266
282
|
// The return-type class has the same two-sided evidence: the declared tokens
|
|
267
283
|
// still say what the correction contradicts, and the slot prose still states the
|
|
268
284
|
// contradiction. A target that fixes either half no longer needs the entry.
|
|
@@ -273,9 +289,16 @@ const RETURN_VERDICT_RANK: Record<ReturnVerdict, number> = {
|
|
|
273
289
|
// return correction replaces the whole emitted type, so a base upstream no longer
|
|
274
290
|
// declares means the correction now overwrites a type nobody verified — a
|
|
275
291
|
// decision for a human, not a deletion and not a silent bank.
|
|
292
|
+
//
|
|
293
|
+
// A binding-pinned entry rests on the engine source rather than the prose, so
|
|
294
|
+
// its prose is never searched. `bindingEvidence` maps each vendored target to
|
|
295
|
+
// the keys whose pin holds there; a target absent from it shows no evidence.
|
|
296
|
+
// A target without the entry's evidence is `unbound` before its tokens are
|
|
297
|
+
// read, because the emitter leaves the entry off there.
|
|
276
298
|
export function returnCorrectionProvenance(
|
|
277
299
|
entries: readonly [string, ReturnTypeCorrection][],
|
|
278
300
|
surfaces: readonly ProvenanceSurface[],
|
|
301
|
+
bindingEvidence: ReadonlyMap<string, ReadonlySet<string>> = new Map(),
|
|
279
302
|
): ReturnTypeProvenance[] {
|
|
280
303
|
return entries.map(([key, correction]) => {
|
|
281
304
|
const namespace = namespaceOf(key);
|
|
@@ -291,7 +314,12 @@ export function returnCorrectionProvenance(
|
|
|
291
314
|
const tokens = slot.types ?? [];
|
|
292
315
|
|
|
293
316
|
let verdict: ReturnVerdict;
|
|
294
|
-
if (
|
|
317
|
+
if (
|
|
318
|
+
correction.binding !== undefined &&
|
|
319
|
+
bindingEvidence.get(surface.target)?.has(key) !== true
|
|
320
|
+
) {
|
|
321
|
+
verdict = "unbound";
|
|
322
|
+
} else if (!pinMatches(tokens, pins)) {
|
|
295
323
|
verdict = "drift";
|
|
296
324
|
const messages = drift.get(surface.target) ?? new Set<string>();
|
|
297
325
|
drift.set(surface.target, messages);
|
|
@@ -299,8 +327,9 @@ export function returnCorrectionProvenance(
|
|
|
299
327
|
`${surface.target}: pinned ${pins.map((pin) => pin.join("|")).join(" or ")}, found ${tokens.join("|")}`,
|
|
300
328
|
);
|
|
301
329
|
} else if (
|
|
302
|
-
tokens
|
|
303
|
-
|
|
330
|
+
declaresCorrection(tokens, correction) ||
|
|
331
|
+
(correction.binding === undefined &&
|
|
332
|
+
!decodeSlotProse(slot.doc ?? "").includes(correction.reason))
|
|
304
333
|
) {
|
|
305
334
|
verdict = "resolved";
|
|
306
335
|
} else {
|
|
@@ -323,6 +352,7 @@ export function returnCorrectionProvenance(
|
|
|
323
352
|
sightedIn,
|
|
324
353
|
neededBy: inBucket("needed"),
|
|
325
354
|
resolvedIn: inBucket("resolved"),
|
|
355
|
+
unboundIn: inBucket("unbound"),
|
|
326
356
|
driftedIn,
|
|
327
357
|
typeDrift: driftedIn.flatMap((target) => [...(drift.get(target) ?? [])]).sort(),
|
|
328
358
|
};
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
// params, and the `WINDOW_EVENT_*` constants are branded numbers — so TS can
|
|
5
5
|
// neither correlate the two params nor use a branded number as a discriminant.
|
|
6
6
|
// This guard re-introduces the discriminant at the use site, narrowing the
|
|
7
|
-
// untyped `data` payload (only `WINDOW_EVENT_RESIZED` carries fields
|
|
7
|
+
// untyped `data` payload (only `WINDOW_EVENT_RESIZED` carries fields; every
|
|
8
|
+
// other event gets an empty table, script_window.cpp). It mirrors
|
|
8
9
|
// `isMessage` for `on_message`; the transpiler lowers the call to a bare
|
|
9
10
|
// `event == window.WINDOW_EVENT_*` (window-event-guard-lowering.ts), so this
|
|
10
11
|
// package emits no runtime Lua. The event kinds are read off the loaded
|
|
@@ -14,7 +15,7 @@ type WindowEventKind = (typeof window)[Extract<keyof typeof window, `WINDOW_EVEN
|
|
|
14
15
|
|
|
15
16
|
type WindowEventData<K extends WindowEventKind> = K extends typeof window.WINDOW_EVENT_RESIZED
|
|
16
17
|
? { width: number; height: number }
|
|
17
|
-
:
|
|
18
|
+
: Record<string, never>;
|
|
18
19
|
|
|
19
20
|
declare global {
|
|
20
21
|
/**
|
|
@@ -24,7 +25,8 @@ declare global {
|
|
|
24
25
|
* params and the constants are branded numbers, so TS cannot auto-narrow `data`
|
|
25
26
|
* from an `event === window.WINDOW_EVENT_RESIZED` check — this guard
|
|
26
27
|
* re-introduces the discriminant. Only `WINDOW_EVENT_RESIZED` carries fields
|
|
27
|
-
* (`{ width, height }`); every other event
|
|
28
|
+
* (`{ width, height }`); every other event receives an empty table, so `data`
|
|
29
|
+
* narrows to `Record<string, never>`.
|
|
28
30
|
*
|
|
29
31
|
* @param event - the event constant the callback received.
|
|
30
32
|
* @param data - the untyped data payload the callback received.
|