# tecs.assets Reads bytes and decodes images and sounds on a worker. Each load returns a [`Future`](/modules/Future/) immediately: ```teal return tecs.newApplication({ plugin = function(world: tecs.World, app: tecs.Application) tecs.assets.loadImage( tecs.io.files.assetPath("sprites/hero.png") ) :map(function(image: tecs.assets.Image): tecs.gfx.Sprite return app.renderer.sprites:registerImage(image) end) :onSettle(function(sprite: tecs.Future) if sprite.status == "ready" then world:spawn( tecs.Transform2D(100, 100), sprite.value, tecs.gfx.Renderable2D() ) end end) end, }) ``` The loader decodes pixels but creates no GPU resource. The renderer decides texture residency. Audio follows the same split between decoded clips and voices. `newMesh` constructs immutable procedural geometry synchronously. `loadGLTF` decodes static glTF 2.0 and GLB scenes on the worker, including their images, metallic-roughness materials, alpha masks, and `BLEND` modes. Both produce CPU-owned data that the mesh domain consumes when it becomes resident. A model with a `BLEND` material requires a mesh domain created with `transparency = true`. ## Lifetime [`Application`](/modules/Application/) installs and shuts down the process-wide worker, and [`runtime.poll`](/modules/runtime/#tecs.runtime.poll) updates it. Headless code must call `install`, pump with `tecs.runtime.poll` or wait with `waitAll`, then call `shutdown`. Drain wanted results before shutdown because in-flight futures otherwise remain pending. Cancel a pending future to release one caller's interest. Release a ready payload when its consumer takes ownership. The final release frees the decoded memory. Overlapping image loads for one path share a decode. Each caller receives its own future and a hold on the same image. A later load after settlement decodes again. Sound loads never share. `loadString` reads a complete file into a binary-safe string without interpreting it. Image loads accept PNG, JPEG and static SVG. SVG renders at its intrinsic dimensions. It uses the bundled JetBrains Mono for all text and ignores external image references, so installed fonts and the worker's current directory cannot change its pixels. `tecs.audio.decoders()` reports the sound formats linked into the current build. Sound mode `"resident"` decodes the complete clip, `"stream"` opens a source for each voice, and `"auto"` chooses from the duration threshold. Use `Future.all` to join independent loads. Release each ready payload after its consumer takes ownership. ## Module contents ### Constructors | Constructor | Description | | --- | --- | | [`newMesh`](/modules/assets/#tecs.assets.newMesh) | Builds procedural mesh data in the renderer's fixed vertex layout. | ### Types | Type | Kind | Description | | --- | --- | --- | | [`Image`](/modules/assets/#tecs.assets.Image) | record | Represents decoded pixels and the caller's hold on them. | | [`Mesh`](/modules/assets/#tecs.assets.Mesh) | record | Describes one immutable indexed triangle mesh before GPU registration. | | [`MeshOptions`](/modules/assets/#tecs.assets.MeshOptions) | record | Supplies procedural geometry to newMesh. | | [`Model`](/modules/assets/#tecs.assets.Model) | record | Represents one decoded static glTF 2.0 scene. | | [`ModelDraw`](/modules/assets/#tecs.assets.ModelDraw) | record | Describes one static primitive instance in a decoded glTF scene. | | [`ModelMaterial`](/modules/assets/#tecs.assets.ModelMaterial) | record | Describes one decoded glTF material before GPU registration. | | [`Sound`](/modules/assets/#tecs.assets.Sound) | record | Represents a loaded clip and the caller's hold on it. | ### Functions | Function | Kind | Description | | --- | --- | --- | | [`install`](/modules/assets/#tecs.assets.install) | Static | Starts the loading worker. | | [`installed`](/modules/assets/#tecs.assets.installed) | Static | Reports whether the loading worker is running. | | [`loadGLTF`](/modules/assets/#tecs.assets.loadGLTF) | Static | Queues static glTF 2.0 or GLB decoding on the asset worker. | | [`loadImage`](/modules/assets/#tecs.assets.loadImage) | Static | Queues an image for loading and answers a future for it immediately. | | [`loadSound`](/modules/assets/#tecs.assets.loadSound) | Static | Queues a sound for loading and answers a future for it immediately. | | [`loadString`](/modules/assets/#tecs.assets.loadString) | Static | Queues a complete file read and answers a future for its bytes immediately. | | [`pending`](/modules/assets/#tecs.assets.pending) | Static | Returns the number of loads still waiting on the worker. | | [`shutdown`](/modules/assets/#tecs.assets.shutdown) | Static | Stops the loading worker. | | [`update`](/modules/assets/#tecs.assets.update) | Static | Takes finished loads and settles their futures. | | [`waitAll`](/modules/assets/#tecs.assets.waitAll) | Static | Blocks until every queued load has finished. | ## Constructors ### tecs.assets.newMesh Static Builds procedural mesh data in the renderer's fixed vertex layout. ```teal function tecs.assets.newMesh(options: MeshOptions): Mesh ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | [`MeshOptions`](/modules/assets/#tecs.assets.MeshOptions) | The caller supplies a name, interleaved vertices, and zero-based triangle indices. | #### Returns | Type | Description | | --- | --- | | [`Mesh`](/modules/assets/#tecs.assets.Mesh) | Returns CPU geometry that `renderer.meshes:registerMesh` consumes or the caller releases. | ## Types ### tecs.assets.Image record Represents decoded pixels and the caller's hold on them. What a `loadImage` future settles to. Reference counts govern the pixels rather than owned outright, because two loads of one path that overlap share a decode: each caller holds the same `Image`, and the last caller to release it one that frees. Reading `pixels` after that is reading freed memory, which is why a released image reads nil there rather than looking uploadable. Read-only. Exposes the decoded image type. ```teal record tecs.assets.Image path: string pixels: loader.CValue width: integer height: integer pitch: integer release: function(self) end ``` #### tecs.assets.Image.path field Read-only. Contains the requested path unchanged. The loader does not resolve it, so it is whatever the caller passed. ```teal tecs.assets.Image.path: string ``` #### tecs.assets.Image.pixels field Read-only. Contains decoded RGBA pixels until the last `release`, then becomes nil. ```teal tecs.assets.Image.pixels: loader.CValue ``` #### tecs.assets.Image.width field Read-only. Reports the width in pixels. ```teal tecs.assets.Image.width: integer ``` #### tecs.assets.Image.height field Read-only. Reports the height in pixel rows. ```teal tecs.assets.Image.height: integer ``` #### tecs.assets.Image.pitch field Read-only. Reports the row stride in bytes, which a decoder may pad beyond `width * 4`. ```teal tecs.assets.Image.pitch: integer ``` #### tecs.assets.Image:release Instance Gives up this caller's hold on the pixels, and frees at the last. Called once whatever needed them has taken a copy, which for an image means after the caller uploads it. Where several loads shared one decode, this releases one of them. Releasing an image already down to nothing does nothing, so a shutdown path need not know whether something else got there first. ```teal function tecs.assets.Image.release(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Image` | | ##### Returns None. ### tecs.assets.Mesh record Describes one immutable indexed triangle mesh before GPU registration. Vertices use one fixed interleaved layout: position xyz, normal xyz, tangent xyzw, and texture uv. Indices are zero-based unsigned 32-bit values. A mesh may therefore contain far more than 65,535 vertices, and a primitive is one indexed range rather than one triangle. `renderer.meshes:registerMesh` copies both arrays into device-local storage and releases this object. The Lua-number constructor is intended for procedural and example geometry. A file decoder can build the same record directly without expanding a large mesh into Lua tables. Read-only. Exposes the immutable CPU mesh type. ```teal record tecs.assets.Mesh name: string vertices: loader.CArray indices: loader.CArray vertexCount: integer indexCount: integer centerX: number centerY: number centerZ: number radius: number release: function(self) end ``` #### tecs.assets.Mesh.name field Read-only. Contains the stable name used by `meshId` and snapshots. ```teal tecs.assets.Mesh.name: string ``` #### tecs.assets.Mesh.vertices field Read-only. Contains interleaved vertex floats until `release` runs. ```teal tecs.assets.Mesh.vertices: loader.CArray ``` #### tecs.assets.Mesh.indices field Read-only. Contains zero-based unsigned 32-bit indices until `release` runs. ```teal tecs.assets.Mesh.indices: loader.CArray ``` #### tecs.assets.Mesh.vertexCount field Read-only. Reports the number of vertices, not floats. ```teal tecs.assets.Mesh.vertexCount: integer ``` #### tecs.assets.Mesh.indexCount field Read-only. Reports the number of indices. It is always a multiple of three. ```teal tecs.assets.Mesh.indexCount: integer ``` #### tecs.assets.Mesh.centerX field Read-only. Reports the local-space bounding-sphere center x. ```teal tecs.assets.Mesh.centerX: number ``` #### tecs.assets.Mesh.centerY field Read-only. Reports the local-space bounding-sphere center y. ```teal tecs.assets.Mesh.centerY: number ``` #### tecs.assets.Mesh.centerZ field Read-only. Reports the local-space bounding-sphere center z. ```teal tecs.assets.Mesh.centerZ: number ``` #### tecs.assets.Mesh.radius field Read-only. Reports the non-negative local-space bounding-sphere radius. ```teal tecs.assets.Mesh.radius: number ``` #### tecs.assets.Mesh:release Instance Gives up the CPU geometry. Calling it again does nothing. ```teal function tecs.assets.Mesh.release(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Mesh` | | ##### Returns None. ### tecs.assets.MeshOptions record Supplies procedural geometry to `newMesh`. ```teal global record tecs.assets.MeshOptions name: string vertices: {number} indices: {integer} end ``` #### tecs.assets.MeshOptions.name field Caller-writable. Supplies the stable non-empty mesh name. ```teal tecs.assets.MeshOptions.name: string ``` #### tecs.assets.MeshOptions.vertices field Caller-writable. Supplies interleaved position xyz, normal xyz, tangent xyzw, and texture uv floats. ```teal tecs.assets.MeshOptions.vertices: {number} ``` #### tecs.assets.MeshOptions.indices field Caller-writable. Supplies zero-based triangle indices. ```teal tecs.assets.MeshOptions.indices: {integer} ``` ### tecs.assets.Model record Represents one decoded static glTF 2.0 scene. Meshes use the same fixed vertex layout as `newMesh`. Images remain decoded CPU pixels. `renderer.meshes:registerModel` consumes all of them and returns spawnable primitive records. Skinning, morph targets, animation are deliberately outside this static lane. Read-only. Exposes the decoded static glTF scene type. ```teal record tecs.assets.Model path: string meshes: {Mesh} images: {Image} materials: {ModelMaterial} draws: {ModelDraw} release: function(self) end ``` #### tecs.assets.Model.path field Read-only. Contains the requested `.gltf` or `.glb` path unchanged. ```teal tecs.assets.Model.path: string ``` #### tecs.assets.Model.meshes field Read-only. Contains unique decoded primitive geometry. ```teal tecs.assets.Model.meshes: {Mesh} ``` #### tecs.assets.Model.images field Read-only. Contains unique decoded source images. ```teal tecs.assets.Model.images: {Image} ``` #### tecs.assets.Model.materials field Read-only. Contains decoded metallic-roughness material descriptions. ```teal tecs.assets.Model.materials: {ModelMaterial} ``` #### tecs.assets.Model.draws field Read-only. Contains the selected scene's flattened static draws. ```teal tecs.assets.Model.draws: {ModelDraw} ``` #### tecs.assets.Model:release Instance Releases every CPU mesh and image not already consumed. Calling it again does nothing. ```teal function tecs.assets.Model.release(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Model` | | ##### Returns None. ### tecs.assets.ModelDraw record Describes one static primitive instance in a decoded glTF scene. Read-only. Exposes one flattened glTF primitive instance. ```teal record tecs.assets.ModelDraw mesh: integer material: integer x: number y: number z: number rotationX: number rotationY: number rotationZ: number rotationW: number scaleX: number scaleY: number scaleZ: number end ``` #### tecs.assets.ModelDraw.mesh field Read-only. Selects a one-based entry in `Model.meshes`. ```teal tecs.assets.ModelDraw.mesh: integer ``` #### tecs.assets.ModelDraw.material field Read-only. Selects a one-based entry in `Model.materials`, or zero for the neutral material. ```teal tecs.assets.ModelDraw.material: integer ``` #### tecs.assets.ModelDraw.x field Read-only. Reports world translation x from the selected glTF scene. ```teal tecs.assets.ModelDraw.x: number ``` #### tecs.assets.ModelDraw.y field Read-only. Reports world translation y. ```teal tecs.assets.ModelDraw.y: number ``` #### tecs.assets.ModelDraw.z field Read-only. Reports world translation z. ```teal tecs.assets.ModelDraw.z: number ``` #### tecs.assets.ModelDraw.rotationX field Read-only. Reports world quaternion x. ```teal tecs.assets.ModelDraw.rotationX: number ``` #### tecs.assets.ModelDraw.rotationY field Read-only. Reports world quaternion y. ```teal tecs.assets.ModelDraw.rotationY: number ``` #### tecs.assets.ModelDraw.rotationZ field Read-only. Reports world quaternion z. ```teal tecs.assets.ModelDraw.rotationZ: number ``` #### tecs.assets.ModelDraw.rotationW field Read-only. Reports world quaternion w. ```teal tecs.assets.ModelDraw.rotationW: number ``` #### tecs.assets.ModelDraw.scaleX field Read-only. Reports world scale x. ```teal tecs.assets.ModelDraw.scaleX: number ``` #### tecs.assets.ModelDraw.scaleY field Read-only. Reports world scale y. ```teal tecs.assets.ModelDraw.scaleY: number ``` #### tecs.assets.ModelDraw.scaleZ field Read-only. Reports world scale z. ```teal tecs.assets.ModelDraw.scaleZ: number ``` ### tecs.assets.ModelMaterial record Describes one decoded glTF material before GPU registration. Read-only. Exposes one glTF material description. ```teal record tecs.assets.ModelMaterial name: string model: integer alphaMode: integer baseColorImage: integer normalImage: integer metallicRoughnessImage: integer occlusionImage: integer emissiveImage: integer alphaCutoff: number baseR: number baseG: number baseB: number baseA: number emissiveR: number emissiveG: number emissiveB: number metallic: number roughness: number normalScale: number occlusionStrength: number end ``` #### tecs.assets.ModelMaterial.name field Read-only. Contains the stable material name. ```teal tecs.assets.ModelMaterial.name: string ``` #### tecs.assets.ModelMaterial.model field Read-only. Selects metallic-roughness PBR at zero or unlit at one. ```teal tecs.assets.ModelMaterial.model: integer ``` #### tecs.assets.ModelMaterial.alphaMode field Read-only. Selects opaque, masked, or blended rendering with a `MeshDomain.ALPHA_*` integer constant. ```teal tecs.assets.ModelMaterial.alphaMode: integer ``` #### tecs.assets.ModelMaterial.baseColorImage field Read-only. Selects a one-based entry in `Model.images`, or zero. ```teal tecs.assets.ModelMaterial.baseColorImage: integer ``` #### tecs.assets.ModelMaterial.normalImage field Read-only. Selects a tangent-space normal image, or zero. ```teal tecs.assets.ModelMaterial.normalImage: integer ``` #### tecs.assets.ModelMaterial.metallicRoughnessImage field Read-only. Selects a glTF metallic-roughness image, or zero. ```teal tecs.assets.ModelMaterial.metallicRoughnessImage: integer ``` #### tecs.assets.ModelMaterial.occlusionImage field Read-only. Selects an occlusion image, or zero. ```teal tecs.assets.ModelMaterial.occlusionImage: integer ``` #### tecs.assets.ModelMaterial.emissiveImage field Read-only. Selects an emissive image, or zero. ```teal tecs.assets.ModelMaterial.emissiveImage: integer ``` #### tecs.assets.ModelMaterial.alphaCutoff field Read-only. Reports the alpha-mask cutoff. Zero keeps every fragment. ```teal tecs.assets.ModelMaterial.alphaCutoff: number ``` #### tecs.assets.ModelMaterial.baseR field Read-only. Reports the base-color red factor. ```teal tecs.assets.ModelMaterial.baseR: number ``` #### tecs.assets.ModelMaterial.baseG field Read-only. Reports the base-color green factor. ```teal tecs.assets.ModelMaterial.baseG: number ``` #### tecs.assets.ModelMaterial.baseB field Read-only. Reports the base-color blue factor. ```teal tecs.assets.ModelMaterial.baseB: number ``` #### tecs.assets.ModelMaterial.baseA field Read-only. Reports the base-color alpha factor. ```teal tecs.assets.ModelMaterial.baseA: number ``` #### tecs.assets.ModelMaterial.emissiveR field Read-only. Reports the emissive red factor. ```teal tecs.assets.ModelMaterial.emissiveR: number ``` #### tecs.assets.ModelMaterial.emissiveG field Read-only. Reports the emissive green factor. ```teal tecs.assets.ModelMaterial.emissiveG: number ``` #### tecs.assets.ModelMaterial.emissiveB field Read-only. Reports the emissive blue factor. ```teal tecs.assets.ModelMaterial.emissiveB: number ``` #### tecs.assets.ModelMaterial.metallic field Read-only. Reports the metallic factor. ```teal tecs.assets.ModelMaterial.metallic: number ``` #### tecs.assets.ModelMaterial.roughness field Read-only. Reports the roughness factor. ```teal tecs.assets.ModelMaterial.roughness: number ``` #### tecs.assets.ModelMaterial.normalScale field Read-only. Reports tangent-space normal strength. ```teal tecs.assets.ModelMaterial.normalScale: number ``` #### tecs.assets.ModelMaterial.occlusionStrength field Read-only. Reports sampled occlusion strength. ```teal tecs.assets.ModelMaterial.occlusionStrength: number ``` ### tecs.assets.Sound record Represents a loaded clip and the caller's hold on it. What a `loadSound` future settles to. Two overlapping loads of one path do not share, unlike images, so a `Sound` normally has one holder; the count is here so that releasing twice frees once rather than twice. Read-only. Exposes the loaded sound type. ```teal record tecs.assets.Sound path: string audio: loader.CValue resident: boolean durationMs: integer release: function(self) end ``` #### tecs.assets.Sound.path field Read-only. Contains the requested path unchanged. ```teal tecs.assets.Sound.path: string ``` #### tecs.assets.Sound.audio field Read-only. Contains the loaded clip until the last `release`. It is nil for one that streams, which holds nothing, and nil once released. ```teal tecs.assets.Sound.audio: loader.CValue ``` #### tecs.assets.Sound.resident field Read-only. Reports whether memory holds the decoded audio. It is false for a clip each voice reads from the file for itself. ```teal tecs.assets.Sound.resident: boolean ``` #### tecs.assets.Sound.durationMs field Read-only. Reports the length in milliseconds, or -1 when the container cannot say. ```teal tecs.assets.Sound.durationMs: integer ``` #### tecs.assets.Sound:release Instance Gives up this caller's hold on the clip, and frees at the last. A voice reads a clip where it lies, so release a clip when nothing will play it again. A track holds its own reference, so releasing one that is still sounding is safe: the mixer drops it when the last track using it does. Releasing a clip already down to nothing does nothing. ```teal function tecs.assets.Sound.release(self) ``` ##### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Sound` | | ##### Returns None. ## Functions ### tecs.assets.install Static Starts the loading worker. Installing twice is installing once. Spawning unconditionally would leave the first thread running with both its channels and nothing reading them, and every queued decode would answer into an abandoned channel, so a load in flight across the second call would never resolve. ```teal function tecs.assets.install(luaPath: string) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `luaPath` | `string` | `package.path` for the worker's own state, which shares no loaded modules with this one. Defaults to this state's, which is what makes the worker resolve the same modules the game does. | #### Returns None. ### tecs.assets.installed Static Reports whether the loading worker is running. For a subsystem that loads an asset of its own and has no way of knowing whether the game has started the worker yet. ```teal function tecs.assets.installed(): boolean ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `boolean` | Whether the worker exists, which is a fact about the process rather than about any world. False means a load raises rather than queueing, so this is the guard rather than an optimization. | ### tecs.assets.loadGLTF Static Queues static glTF 2.0 or GLB decoding on the asset worker. External buffers and images resolve relative to the model path. Data URIs and embedded GLB resources are supported. Triangle primitives, static node transforms, metallic-roughness PBR, normal, occlusion, emissive, alpha-mask, alpha-blended, and unlit materials are decoded. A skinned, morphed, animated, sparse-accessor, or non-triangle input settles as failed instead of being loaded incompletely. Registering a model containing alpha blending requires a mesh domain created with `transparency = true`. ```teal function tecs.assets.loadGLTF(path: string): Future ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `path` | `string` | The caller supplies a `.gltf` or `.glb` asset path. | #### Returns | Type | Description | | --- | --- | | [`Future`](/modules/Future/)`<`[`Model`](/modules/assets/#tecs.assets.Model)`>` | Returns a pending future that owns its ready model. | ### tecs.assets.loadImage Static Queues an image for loading and answers a future for it immediately. Two loads of one path that overlap share a decode, because decoding the same PNG twice at once duplicates work without producing another result. They share the [`Image`](/modules/assets/#tecs.assets.Image), so the last caller to release it one that frees, and each of them holds a future of its own, so one canceling is invisible to the others. A load that starts after the first has settled decodes again: nothing here is a cache. ```teal function tecs.assets.loadImage(path: string): Future ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `path` | `string` | The caller supplies a PNG, JPEG or static SVG path. The loader renders SVG at its intrinsic width and height, uses bundled JetBrains Mono for text, and ignores external image references. Another format fails during decoding. | #### Returns | Type | Description | | --- | --- | | [`Future`](/modules/Future/)`<`[`Image`](/modules/assets/#tecs.assets.Image)`>` | A pending future, never nil. Raises instead when `install` has not run. Failures reach it as a failed settlement, not through this call: a missing file is a future that fails once the worker has looked. Canceling it gives up this caller's interest in the decode, and the last caller to do so abandons it. | ### tecs.assets.loadSound Static Queues a sound for loading and answers a future for it immediately. Whatever the mixer's decoders can read loads, so the format is the file's business rather than the caller's. `mode` is "resident", "stream", or "auto", and auto keeps anything shorter than `streamMs` resident. This call initializes the library instead of the worker because `MIX_Init` does not support concurrent calls. Initialization before sending the task puts it in order ahead of every decode without a lock. Two overlapping loads of one path do not share, unlike images: each gets its own clip, because that is what `MIX_LoadAudio` produces. So this answers the root future rather than a link over one, and the [`Sound`](/modules/assets/#tecs.assets.Sound) it settles to has exactly one holder. ```teal function tecs.assets.loadSound( path: string, mode: string, streamMs: integer ): Future ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `path` | `string` | | | `mode` | `string` | "resident", "stream" or "auto". Any other value selects "stream". | | `streamMs` | `integer` | The boundary "auto" decides on, in milliseconds. Read only under "auto", and a file whose length the container cannot state streams whatever it says. | #### Returns | Type | Description | | --- | --- | | [`Future`](/modules/Future/)`<`[`Sound`](/modules/assets/#tecs.assets.Sound)`>` | A pending future, or a failed future when mixer initialization fails. This is the only failure reported without waiting for the worker. | ### tecs.assets.loadString Static Queues a complete file read and answers a future for its bytes immediately. The returned string preserves embedded NUL bytes. Overlapping reads of one path share the worker task while each caller receives its own future, so one caller may cancel without affecting another. A later read after settlement reads the file again. ```teal function tecs.assets.loadString( path: string, kind: string ): Future ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `path` | `string` | The caller supplies an absolute path or one from [`assetPath`](/modules/io/files/#tecs.io.files.assetPath). | | `kind` | `string` | The caller supplies the content kind used by file watching, or omits it to record a document. | #### Returns | Type | Description | | --- | --- | | [`Future`](/modules/Future/)`` | Returns a pending [`Future`](/modules/Future/). A missing or unreadable file settles it as failed. | ### tecs.assets.pending Static Returns the number of loads still waiting on the worker. ```teal function tecs.assets.pending(): integer ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `integer` | Every load in flight in this process, not one caller's. A load every caller has canceled is still counted until the worker answers for it, because the address it sends still has to be taken and destroyed. | ### tecs.assets.shutdown Static Stops the loading worker. Blocks until the thread exits. This call drops loads still in flight and leaves their futures pending forever, so drain with `waitAll` first when their results matter. Releasing an [`Image`](/modules/assets/#tecs.assets.Image) or a [`Sound`](/modules/assets/#tecs.assets.Sound) that already settled still works afterwards; this frees nothing. ```teal function tecs.assets.shutdown() ``` #### Arguments None. #### Returns None. ### tecs.assets.update Static Takes finished loads and settles their futures. Call once per frame. Polls, never blocks, and drains everything the worker has answered rather than one result. Nothing settles without this, so a game that stops calling it has loads that stay pending forever. ```teal function tecs.assets.update(): integer ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `integer` | How many loads settled this call, which is zero when nothing has finished and also zero when no worker exists. | ### tecs.assets.waitAll Static Blocks until every queued load has finished. For startup and tests. A frame should poll `update` instead. Not a join over futures a caller holds, and no join expresses it: this waits on every load in this process, including ones a subsystem the caller has never heard of started, which is what a reload or a startup path wants. ```teal function tecs.assets.waitAll(timeoutMs: number) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `timeoutMs` | `number` | Wall-clock milliseconds, defaulting to 5000. Running out is not an error and is not reported, so read `assets.pending` afterwards to tell the two endings apart. | #### Returns None.