On this page
  1. tecs.assets
  2. Lifetime
  3. Module contents
    1. Constructors
    2. Types
    3. Functions
    4. Values
  4. Constructors
    1. newMesh
  5. Types
    1. Image
    2. Mesh
    3. MeshMorphTarget
    4. MeshOptions
    5. Model
    6. ModelAnimation
    7. ModelAnimationChannel
    8. ModelDraw
    9. ModelMaterial
    10. ModelNode
    11. ModelSkin
    12. Sound
  6. Functions
    1. install
    2. installed
    3. loadGLTF
    4. loadImage
    5. loadSound
    6. loadString
    7. pending
    8. shutdown
    9. waitAll
  7. Values
    1. ANIMATION_CUBIC
    2. ANIMATION_LINEAR
    3. ANIMATION_ROTATION
    4. ANIMATION_SCALE
    5. ANIMATION_STEP
    6. ANIMATION_TRANSLATION
    7. ANIMATION_WEIGHTS
    8. IMAGE_BC3
    9. IMAGE_RGBA8

tecs.assets

Acquires and decodes assets without blocking the SDL host.

Loads return their values directly. Inside a frame system dispatched by world:update, a worker decode transparently suspends the logical update:

return tecs.newApplication({
    plugin = function(world: tecs.World, app: tecs.Application)
        local loaded = false
        world:addSystem({
            name = "game.SpawnHero",
            phase = tecs.ecs.phases.PreUpdate,
            run = function()
                if loaded then
                    return
                end
                local image <const> = tecs.assets.loadImage(
                    tecs.io.files.assetPath("sprites/hero.png")
                )
                local sprite <const> = app.renderer.sprites:registerImage(image)
                world:spawn(
                    tecs.Transform2D(100, 100),
                    sprite,
                    tecs.gfx.Renderable2D()
                )
                loaded = true
            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.

Image cache misses read through SDL AsyncIO, decode in the bounded native CPU lane, and publish on the main thread. newMesh constructs immutable procedural geometry synchronously. loadGLTF decodes glTF 2.0 and GLB scenes through the maintained Rust glTF importer on a warmed isolated worker, including images, metallic-roughness materials, vertex colors, alpha masks, BLEND modes, skins, and node animation clips including morph weights. One opaque native allocation retains the import; the main thread borrows its geometry through flat views instead of serializing large strings through the worker channel. 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.

Primitives without authored tangents use MikkTSpace tangent generation. Tangent discontinuities split vertices while color, skin, and morph streams follow the split, preserving normal-map seams without changing authored tangents.

One imported primitive becomes one independently bounded GPU-culling command. The decoder splits a primitive above 65,536 triangles into bounded commands, remapping the vertices and optional color, skin, and morph streams in each chunk. Meshoptimizer then reorders opaque and masked triangles for the vertex cache and remaps every vertex stream into first-use order. Alpha-blended triangles retain their authored order because order affects their result, but their vertex streams still receive the lossless fetch remap.

The repository's large-scene fetch command can replace source images with complete BC3 mip chains in KTX2 containers. The maintained Rust parser validates the container before exposing its blocks. Those images remain compressed through upload and require a mesh domain created with textureFormat = tecs.assets.IMAGE_BC3, mipmaps = true, and packTextures = false. PNG, JPEG, SVG, and ordinary glTF images remain decoded RGBA8.

Lifetime

Application installs and shuts down the asset lanes. Headless code calls install before model or sound loading and shutdown afterwards. A load outside a world update blocks and drives its private producer until the value or failure arrives; a system suspends at the same direct call.

Release a payload after its consumer takes ownership. The final release frees the decoded memory.

Overlapping image loads for one path share a decode and receive holds 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, static SVG, and linear BC3 KTX2 mip chains. 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.

Release each payload after its consumer takes ownership.

Module contents

Constructors

Constructor Description
newMesh Builds procedural mesh data in the renderer's fixed vertex layout.

Types

Type Kind Description
Image record Represents decoded pixels or an imported compressed mip chain and the caller's hold on them.
Mesh record Describes one immutable indexed triangle mesh before GPU registration.
MeshMorphTarget record Supplies one procedural morph target to newMesh.
MeshOptions record Supplies procedural geometry to newMesh.
Model record Represents one decoded glTF 2.0 scene and its node animations.
ModelAnimation record Describes one decoded glTF node-animation clip.
ModelAnimationChannel record Describes one decoded glTF animation channel.
ModelDraw record Describes one static primitive instance in a decoded glTF scene.
ModelMaterial record Describes one decoded glTF material before GPU registration.
ModelNode record Describes one node in a decoded glTF transform hierarchy.
ModelSkin record Describes one initial joint palette decoded from a glTF skin instance.
Sound record Represents a loaded clip and the caller's hold on it.

Functions

Function Kind Description
install Static Starts the loading worker.
installed Static Reports whether the loading worker is running.
loadGLTF Static Queues glTF 2.0 or GLB decoding on the asset worker.
loadImage Static Loads an image and returns its decoded pixels.
loadSound Static Loads a sound and returns its decoded or streaming payload.
loadString Static Reads a complete file and returns its bytes.
pending Static Returns the number of asset loads still in flight.
shutdown Static Stops the loading worker.
waitAll Static Blocks until every queued load has finished.

Values

Value Type Description
ANIMATION_CUBIC integer Read-only. Selects cubic-spline interpolation.
ANIMATION_LINEAR integer Read-only. Selects linear interpolation.
ANIMATION_ROTATION integer Read-only. Selects a rotation animation channel.
ANIMATION_SCALE integer Read-only. Selects a scale animation channel.
ANIMATION_STEP integer Read-only. Selects held-key interpolation.
ANIMATION_TRANSLATION integer Read-only. Selects a translation animation channel.
ANIMATION_WEIGHTS integer Read-only. Selects a morph-weight animation channel.
IMAGE_BC3 integer Read-only. Selects a complete imported BC3 image mip chain.
IMAGE_RGBA8 integer Read-only. Selects decoded, uncompressed RGBA8 image storage.

Constructors

tecs.assets.newMesh Static

Builds procedural mesh data in the renderer's fixed vertex layout.

function tecs.assets.newMesh(options: MeshOptions): Mesh

Arguments

Name Type Description
options MeshOptions The caller supplies a name, interleaved vertices, and zero-based triangle indices.

Returns

Type Description
Mesh Returns CPU geometry that renderer.meshes:registerMesh consumes or the caller releases.

Types

tecs.assets.Image record

Represents decoded pixels or an imported compressed mip chain and the caller's hold on them.

What loadImage returns. Reference counts govern the pixels rather than owning them outright, because two overlapping loads 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.

record tecs.assets.Image
    path: string
    pixels: loader.CValue
    width: integer
    height: integer
    pitch: integer
    format: integer
    storageWidth: integer
    storageHeight: integer
    levels: integer
    byteCount: 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.

tecs.assets.Image.path: string

tecs.assets.Image.pixels field

Read-only. Contains decoded RGBA pixels or BC3 blocks until the last release, then becomes nil.

tecs.assets.Image.pixels: loader.CValue

tecs.assets.Image.width field

Read-only. Reports the width in pixels.

tecs.assets.Image.width: integer

tecs.assets.Image.height field

Read-only. Reports the height in pixel rows.

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.

tecs.assets.Image.pitch: integer

tecs.assets.Image.format field

Read-only. Selects decoded RGBA8 pixels or an imported BC3 mip chain with an assets.IMAGE_* integer constant.

tecs.assets.Image.format: integer

tecs.assets.Image.storageWidth field

Read-only. Reports the texture width represented by the uploaded mip chain. It equals width for decoded RGBA8 images.

tecs.assets.Image.storageWidth: integer

tecs.assets.Image.storageHeight field

Read-only. Reports the texture height represented by the uploaded mip chain. It equals height for decoded RGBA8 images.

tecs.assets.Image.storageHeight: integer

tecs.assets.Image.levels field

Read-only. Reports the number of consecutive mip levels in pixels.

tecs.assets.Image.levels: integer

tecs.assets.Image.byteCount field

Read-only. Reports bytes available from pixels. Decoded RGBA8 images report pitch * height.

tecs.assets.Image.byteCount: 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.

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.

record tecs.assets.Mesh
    name: string
    vertices: loader.CArray
    colorVertices: loader.CArray
    indices: loader.CArray
    skinVertices: loader.CArray
    morphVertices: loader.CArray
    morphTargetCount: integer
    morphWeights: {number}
    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.

tecs.assets.Mesh.name: string

tecs.assets.Mesh.vertices field

Read-only. Contains interleaved vertex floats until release runs.

tecs.assets.Mesh.vertices: loader.CArray

tecs.assets.Mesh.colorVertices field

Read-only. Contains optional linear RGBA vertex colors until release runs. Nil means every vertex is white.

tecs.assets.Mesh.colorVertices: loader.CArray

tecs.assets.Mesh.indices field

Read-only. Contains zero-based unsigned 32-bit indices until release runs.

tecs.assets.Mesh.indices: loader.CArray

tecs.assets.Mesh.skinVertices field

Read-only. Contains optional joint indices and weights as eight floats per vertex until release runs. Nil means rigid geometry.

tecs.assets.Mesh.skinVertices: loader.CArray

tecs.assets.Mesh.morphVertices field

Read-only. Contains optional position, normal, and tangent deltas as nine floats per target vertex until release runs. Nil means the geometry has no morph targets.

tecs.assets.Mesh.morphVertices: loader.CArray

tecs.assets.Mesh.morphTargetCount field

Read-only. Reports the number of consecutive morph targets.

tecs.assets.Mesh.morphTargetCount: integer

tecs.assets.Mesh.morphWeights field

Read-only. Contains one default weight per morph target.

tecs.assets.Mesh.morphWeights: {number}

tecs.assets.Mesh.vertexCount field

Read-only. Reports the number of vertices, not floats.

tecs.assets.Mesh.vertexCount: integer

tecs.assets.Mesh.indexCount field

Read-only. Reports the number of indices. It is always a multiple of three.

tecs.assets.Mesh.indexCount: integer

tecs.assets.Mesh.centerX field

Read-only. Reports the local-space bounding-sphere center x.

tecs.assets.Mesh.centerX: number

tecs.assets.Mesh.centerY field

Read-only. Reports the local-space bounding-sphere center y.

tecs.assets.Mesh.centerY: number

tecs.assets.Mesh.centerZ field

Read-only. Reports the local-space bounding-sphere center z.

tecs.assets.Mesh.centerZ: number

tecs.assets.Mesh.radius field

Read-only. Reports the non-negative local-space bounding-sphere radius.

tecs.assets.Mesh.radius: number

tecs.assets.Mesh:release Instance

Gives up the CPU geometry. Calling it again does nothing.

function tecs.assets.Mesh.release(self)
Arguments
Name Type Description
self Mesh
Returns

None.

tecs.assets.MeshMorphTarget record

Supplies one procedural morph target to newMesh. Read-only. Exposes one procedural morph-target description.

record tecs.assets.MeshMorphTarget
    positions: {number}
    normals: {number}
    tangents: {number}
end

tecs.assets.MeshMorphTarget.positions field

Caller-writable. Supplies three position deltas per vertex.

tecs.assets.MeshMorphTarget.positions: {number}

tecs.assets.MeshMorphTarget.normals field

Caller-writable. Supplies three normal deltas per vertex, or nil for zero deltas.

tecs.assets.MeshMorphTarget.normals: {number}

tecs.assets.MeshMorphTarget.tangents field

Caller-writable. Supplies three tangent deltas per vertex, or nil for zero deltas. Tangent handedness is unchanged.

tecs.assets.MeshMorphTarget.tangents: {number}

tecs.assets.MeshOptions record

Supplies procedural geometry to newMesh.

global record tecs.assets.MeshOptions
    name: string
    vertices: {number}
    colors: {number}
    indices: {integer}
    joints: {integer}
    weights: {number}
    morphTargets: {MeshMorphTarget}
    morphWeights: {number}
end

tecs.assets.MeshOptions.name field

Caller-writable. Supplies the stable non-empty mesh name.

tecs.assets.MeshOptions.name: string

tecs.assets.MeshOptions.vertices field

Caller-writable. Supplies interleaved position xyz, normal xyz, tangent xyzw, and texture uv floats.

tecs.assets.MeshOptions.vertices: {number}

tecs.assets.MeshOptions.colors field

Caller-writable. Supplies optional linear RGBA colors, four per vertex. Nil makes every vertex white without allocating a color array.

tecs.assets.MeshOptions.colors: {number}

tecs.assets.MeshOptions.indices field

Caller-writable. Supplies zero-based triangle indices.

tecs.assets.MeshOptions.indices: {integer}

tecs.assets.MeshOptions.joints field

Caller-writable. Supplies four zero-based joint indices per vertex. Nil requires weights to be nil and builds rigid geometry.

tecs.assets.MeshOptions.joints: {integer}

tecs.assets.MeshOptions.weights field

Caller-writable. Supplies four non-negative joint weights per vertex. Each group is normalized by newMesh and requires joints.

tecs.assets.MeshOptions.weights: {number}

tecs.assets.MeshOptions.morphTargets field

Caller-writable. Supplies morph targets in file order. Each target carries vertex-count-matched position deltas and optional normal and tangent deltas.

tecs.assets.MeshOptions.morphWeights field

Caller-writable. Supplies one finite default weight per morph target. Omitted weights default to zero.

tecs.assets.MeshOptions.morphWeights: {number}

tecs.assets.Model record

Represents one decoded glTF 2.0 scene and its node animations.

Meshes use the same fixed vertex layout as newMesh. Images remain decoded CPU pixels. renderer.meshes:registerModel consumes all of them and returns shared residency that creates independently posed instances. Skinning includes the initial joint pose. Morph data includes immutable deltas and default weights. Animation clips retain allocation-stable CPU sampling data for node transforms and morph weights. Read-only. Exposes the decoded glTF scene type.

record tecs.assets.Model
    path: string
    mipmaps: boolean
    meshes: {Mesh}
    images: {Image}
    materials: {ModelMaterial}
    skins: {ModelSkin}
    nodes: {ModelNode}
    animations: {ModelAnimation}
    draws: {ModelDraw}

    release: function(self)
end

tecs.assets.Model.path field

Read-only. Contains the requested .gltf or .glb path unchanged.

tecs.assets.Model.path: string

tecs.assets.Model.mipmaps field

Read-only. Reports whether the source sampler requires a complete linearly filtered mip chain.

tecs.assets.Model.mipmaps: boolean

tecs.assets.Model.meshes field

Read-only. Contains unique decoded primitive geometry.

tecs.assets.Model.meshes: {Mesh}

tecs.assets.Model.images field

Read-only. Contains unique decoded source images.

tecs.assets.Model.images: {Image}

tecs.assets.Model.materials field

Read-only. Contains decoded metallic-roughness material descriptions.

tecs.assets.Model.skins field

Read-only. Contains initial joint palettes referenced by model draws.

tecs.assets.Model.skins: {ModelSkin}

tecs.assets.Model.nodes field

Read-only. Contains every node in source-index order.

tecs.assets.Model.nodes: {ModelNode}

tecs.assets.Model.animations field

Read-only. Contains decoded translation, rotation, and scale clips.

tecs.assets.Model.draws field

Read-only. Contains the selected scene's flattened static draws.

tecs.assets.Model.draws: {ModelDraw}

tecs.assets.Model:release Instance

Releases every CPU mesh and image not already consumed. Calling it again does nothing.

function tecs.assets.Model.release(self)
Arguments
Name Type Description
self Model
Returns

None.

tecs.assets.ModelAnimation record

Describes one decoded glTF node-animation clip. Read-only. Exposes one decoded node-animation clip.

record tecs.assets.ModelAnimation
    name: string
    duration: number
    channels: {ModelAnimationChannel}
end

tecs.assets.ModelAnimation.name field

Read-only. Contains the authored clip name or a stable generated name.

tecs.assets.ModelAnimation.name: string

tecs.assets.ModelAnimation.duration field

Read-only. Reports the last key time in seconds.

tecs.assets.ModelAnimation.duration: number

tecs.assets.ModelAnimation.channels field

Read-only. Contains translation, rotation, scale, and morph-weight channels.

tecs.assets.ModelAnimationChannel record

Describes one decoded glTF animation channel. Read-only. Exposes one decoded animation channel.

record tecs.assets.ModelAnimationChannel
    node: integer
    path: integer
    interpolation: integer
    width: integer
    times: {number}
    values: {number}
end

tecs.assets.ModelAnimationChannel.node field

Read-only. Selects a one-based target node.

tecs.assets.ModelAnimationChannel.node: integer

tecs.assets.ModelAnimationChannel.path field

Read-only. Selects ANIMATION_TRANSLATION, ANIMATION_ROTATION, ANIMATION_SCALE, or ANIMATION_WEIGHTS.

tecs.assets.ModelAnimationChannel.path: integer

tecs.assets.ModelAnimationChannel.interpolation field

Read-only. Selects ANIMATION_LINEAR, ANIMATION_STEP, or ANIMATION_CUBIC.

tecs.assets.ModelAnimationChannel.width field

Read-only. Reports packed values per key. It is three for translation and scale, four for rotation, and the target count for morph weights.

tecs.assets.ModelAnimationChannel.width: integer

tecs.assets.ModelAnimationChannel.times field

Read-only. Contains strictly increasing key times in seconds.

tecs.assets.ModelAnimationChannel.times: {number}

tecs.assets.ModelAnimationChannel.values field

Read-only. Contains packed key values. Cubic keys contain incoming tangent, value, and outgoing tangent rows.

tecs.assets.ModelAnimationChannel.values: {number}

tecs.assets.ModelDraw record

Describes one static primitive instance in a decoded glTF scene. Read-only. Exposes one flattened glTF primitive instance.

record tecs.assets.ModelDraw
    mesh: integer
    material: integer
    skin: integer
    node: integer
    weights: {number}
    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.

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.

tecs.assets.ModelDraw.material: integer

tecs.assets.ModelDraw.skin field

Read-only. Selects a one-based entry in Model.skins, or zero for a rigid primitive.

tecs.assets.ModelDraw.skin: integer

tecs.assets.ModelDraw.node field

Read-only. Selects the one-based scene node this primitive follows.

tecs.assets.ModelDraw.node: integer

tecs.assets.ModelDraw.weights field

Read-only. Contains this node's initial morph weights in target order.

tecs.assets.ModelDraw.weights: {number}

tecs.assets.ModelDraw.x field

Read-only. Reports world translation x from the selected glTF scene.

tecs.assets.ModelDraw.x: number

tecs.assets.ModelDraw.y field

Read-only. Reports world translation y.

tecs.assets.ModelDraw.y: number

tecs.assets.ModelDraw.z field

Read-only. Reports world translation z.

tecs.assets.ModelDraw.z: number

tecs.assets.ModelDraw.rotationX field

Read-only. Reports world quaternion x.

tecs.assets.ModelDraw.rotationX: number

tecs.assets.ModelDraw.rotationY field

Read-only. Reports world quaternion y.

tecs.assets.ModelDraw.rotationY: number

tecs.assets.ModelDraw.rotationZ field

Read-only. Reports world quaternion z.

tecs.assets.ModelDraw.rotationZ: number

tecs.assets.ModelDraw.rotationW field

Read-only. Reports world quaternion w.

tecs.assets.ModelDraw.rotationW: number

tecs.assets.ModelDraw.scaleX field

Read-only. Reports world scale x.

tecs.assets.ModelDraw.scaleX: number

tecs.assets.ModelDraw.scaleY field

Read-only. Reports world scale y.

tecs.assets.ModelDraw.scaleY: number

tecs.assets.ModelDraw.scaleZ field

Read-only. Reports world scale z.

tecs.assets.ModelDraw.scaleZ: number

tecs.assets.ModelMaterial record

Describes one decoded glTF material before GPU registration. Read-only. Exposes one glTF material description.

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
    doubleSided: boolean
end

tecs.assets.ModelMaterial.name field

Read-only. Contains the stable material name.

tecs.assets.ModelMaterial.name: string

tecs.assets.ModelMaterial.model field

Caller-writable. Until model registration, selects metallic-roughness PBR at zero, unlit at one, or Lambert diffuse at two. This defaults to the decoded glTF model.

tecs.assets.ModelMaterial.model: integer

tecs.assets.ModelMaterial.alphaMode field

Read-only. Selects opaque, masked, or blended rendering with a MeshDomain.ALPHA_* integer constant.

tecs.assets.ModelMaterial.alphaMode: integer

tecs.assets.ModelMaterial.baseColorImage field

Read-only. Selects a one-based entry in Model.images, or zero.

tecs.assets.ModelMaterial.baseColorImage: integer

tecs.assets.ModelMaterial.normalImage field

Read-only. Selects a tangent-space normal image, or zero.

tecs.assets.ModelMaterial.normalImage: integer

tecs.assets.ModelMaterial.metallicRoughnessImage field

Read-only. Selects a glTF metallic-roughness image, or zero.

tecs.assets.ModelMaterial.occlusionImage field

Read-only. Selects an occlusion image, or zero.

tecs.assets.ModelMaterial.occlusionImage: integer

tecs.assets.ModelMaterial.emissiveImage field

Read-only. Selects an emissive image, or zero.

tecs.assets.ModelMaterial.emissiveImage: integer

tecs.assets.ModelMaterial.alphaCutoff field

Read-only. Reports the alpha-mask cutoff. Zero keeps every fragment.

tecs.assets.ModelMaterial.alphaCutoff: number

tecs.assets.ModelMaterial.baseR field

Read-only. Reports the base-color red factor.

tecs.assets.ModelMaterial.baseR: number

tecs.assets.ModelMaterial.baseG field

Read-only. Reports the base-color green factor.

tecs.assets.ModelMaterial.baseG: number

tecs.assets.ModelMaterial.baseB field

Read-only. Reports the base-color blue factor.

tecs.assets.ModelMaterial.baseB: number

tecs.assets.ModelMaterial.baseA field

Read-only. Reports the base-color alpha factor.

tecs.assets.ModelMaterial.baseA: number

tecs.assets.ModelMaterial.emissiveR field

Read-only. Reports the emissive red factor.

tecs.assets.ModelMaterial.emissiveR: number

tecs.assets.ModelMaterial.emissiveG field

Read-only. Reports the emissive green factor.

tecs.assets.ModelMaterial.emissiveG: number

tecs.assets.ModelMaterial.emissiveB field

Read-only. Reports the emissive blue factor.

tecs.assets.ModelMaterial.emissiveB: number

tecs.assets.ModelMaterial.metallic field

Caller-writable. Until model registration, this multiplies sampled metallic and defaults to the decoded glTF factor.

tecs.assets.ModelMaterial.metallic: number

tecs.assets.ModelMaterial.roughness field

Caller-writable. Until model registration, this multiplies sampled roughness and defaults to the decoded glTF factor.

tecs.assets.ModelMaterial.roughness: number

tecs.assets.ModelMaterial.normalScale field

Read-only. Reports tangent-space normal strength.

tecs.assets.ModelMaterial.normalScale: number

tecs.assets.ModelMaterial.occlusionStrength field

Read-only. Reports sampled occlusion strength.

tecs.assets.ModelMaterial.occlusionStrength: number

tecs.assets.ModelMaterial.doubleSided field

Read-only. Reports whether both triangle faces must render.

tecs.assets.ModelMaterial.doubleSided: boolean

tecs.assets.ModelNode record

Describes one node in a decoded glTF transform hierarchy. Read-only. Exposes one decoded model node.

record tecs.assets.ModelNode
    parent: integer
    x: number
    y: number
    z: number
    rotationX: number
    rotationY: number
    rotationZ: number
    rotationW: number
    scaleX: number
    scaleY: number
    scaleZ: number
    matrix: {number}
end

tecs.assets.ModelNode.parent field

Read-only. Selects the one-based parent node, or zero for a root.

tecs.assets.ModelNode.parent: integer

tecs.assets.ModelNode.x field

Read-only. Contains the base translation x.

tecs.assets.ModelNode.x: number

tecs.assets.ModelNode.y field

Read-only. Contains the base translation y.

tecs.assets.ModelNode.y: number

tecs.assets.ModelNode.z field

Read-only. Contains the base translation z.

tecs.assets.ModelNode.z: number

tecs.assets.ModelNode.rotationX field

Read-only. Contains the base quaternion x.

tecs.assets.ModelNode.rotationX: number

tecs.assets.ModelNode.rotationY field

Read-only. Contains the base quaternion y.

tecs.assets.ModelNode.rotationY: number

tecs.assets.ModelNode.rotationZ field

Read-only. Contains the base quaternion z.

tecs.assets.ModelNode.rotationZ: number

tecs.assets.ModelNode.rotationW field

Read-only. Contains the base quaternion scalar component.

tecs.assets.ModelNode.rotationW: number

tecs.assets.ModelNode.scaleX field

Read-only. Contains the base x scale.

tecs.assets.ModelNode.scaleX: number

tecs.assets.ModelNode.scaleY field

Read-only. Contains the base y scale.

tecs.assets.ModelNode.scaleY: number

tecs.assets.ModelNode.scaleZ field

Read-only. Contains the base z scale.

tecs.assets.ModelNode.scaleZ: number

tecs.assets.ModelNode.matrix field

Read-only. Contains a fixed column-major local matrix when the source node used matrix, or nil when its local matrix is composed from TRS.

tecs.assets.ModelNode.matrix: {number}

tecs.assets.ModelSkin record

Describes one initial joint palette decoded from a glTF skin instance. Read-only. Exposes one decoded initial joint palette.

record tecs.assets.ModelSkin
    name: string
    matrices: {number}
    node: integer
    joints: {integer}
    inverseBindMatrices: {number}
end

tecs.assets.ModelSkin.name field

Read-only. Contains the stable palette name used during registration.

tecs.assets.ModelSkin.name: string

tecs.assets.ModelSkin.matrices field

Read-only. Contains column-major joint matrices, sixteen floats per joint, in the skinned mesh's local coordinate space.

tecs.assets.ModelSkin.matrices: {number}

tecs.assets.ModelSkin.node field

Read-only. Selects the one-based mesh node whose local space contains this palette.

tecs.assets.ModelSkin.node: integer

tecs.assets.ModelSkin.joints field

Read-only. Contains one-based joint-node indices in palette order.

tecs.assets.ModelSkin.joints: {integer}

tecs.assets.ModelSkin.inverseBindMatrices field

Read-only. Contains column-major inverse bind matrices, sixteen floats per joint.

tecs.assets.ModelSkin.inverseBindMatrices: {number}

tecs.assets.Sound record

Represents a loaded clip and the caller's hold on it.

What loadSound returns. 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.

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.

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.

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.

tecs.assets.Sound.resident: boolean

tecs.assets.Sound.durationMs field

Read-only. Reports the length in milliseconds, or -1 when the container cannot say.

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.

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.

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.

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 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. JOINTS0, WEIGHTS0, skins, inverse bind matrices, sparse accessors, morph targets, mesh and node weights, and node animation clips are decoded. Missing tangents are generated with MikkTSpace, splitting vertices at tangent discontinuities and remapping every optional vertex stream. Non-triangle input and texture-coordinate transforms raise at the direct load call instead of loading incompletely. A primitive above 65,536 triangles is split into independently bounded and culled mesh records. Opaque and masked records are optimized for vertex-cache and vertex-fetch locality. Alpha-blended records preserve authored triangle order and receive only the lossless vertex-fetch remap. Registering a model containing alpha blending requires a mesh domain created with transparency = true.

function tecs.assets.loadGLTF(path: string): Model

Arguments

Name Type Description
path string The caller supplies a .gltf or .glb asset path.

Returns

Type Description
Model Returns the decoded model. The call suspends its system while the worker runs, or blocks when called outside a world update.

tecs.assets.loadImage Static

Loads an image and returns its decoded pixels.

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, so the last caller to release it frees the pixels. A load that starts after the first has settled decodes again: nothing here is a cache.

function tecs.assets.loadImage(path: string): Image

Arguments

Name Type Description
path string The caller supplies a PNG, JPEG, static SVG, or linear BC3 KTX2 path. KTX2 input must contain one complete mip chain for one image. 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
Image Returns the decoded image. Inside a system, the call suspends only while its decode is pending. A missing file or decode failure raises.

tecs.assets.loadSound Static

Loads a sound and returns its decoded or streaming payload.

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. The returned Sound has exactly one holder.

function tecs.assets.loadSound(
    path: string, mode: string, streamMs: integer
): Sound

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
Sound Returns the loaded sound. Mixer initialization or decode failure raises.

tecs.assets.loadString Static

Reads a complete file and returns its bytes.

The returned string preserves embedded NUL bytes. The operation uses the common file lane; callers that need retained reuse store the returned immutable string in their own asset resource.

function tecs.assets.loadString(path: string, kind: string): string

Arguments

Name Type Description
path string The caller supplies an absolute path or one from assetPath.
kind string The caller supplies the content kind used by file watching, or omits it to record a document.

Returns

Type Description
string Returns the complete bytes. A missing or unreadable file raises with the platform's own reason behind the path it could not read.

tecs.assets.pending Static

Returns the number of asset loads still in flight.

function tecs.assets.pending(): integer

Arguments

None.

Returns

Type Description
integer Every image decode, model load, and sound load owned by this module, not one caller's. loadString uses the shared file lane directly and is not counted. A model or sound load every caller has canceled remains counted until the worker answer is taken and destroyed.

tecs.assets.shutdown Static

Stops the loading worker.

Blocks until the thread exits. This call cancels loads still in flight, so drain with waitAll first when their results matter. Releasing an Image or a Sound that already settled still works afterwards; this frees nothing.

function tecs.assets.shutdown()

Arguments

None.

Returns

None.

tecs.assets.waitAll Static

Blocks until every queued load has finished.

This global barrier is for startup, shutdown, and tests outside a system. Applications use the process runtime during frames.

It waits on every load in this process, including work a subsystem started, rather than only loads one caller initiated.

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.

Values

tecs.assets.ANIMATION_CUBIC variable

Read-only. Selects cubic-spline interpolation.

tecs.assets.ANIMATION_CUBIC: integer

tecs.assets.ANIMATION_LINEAR variable

Read-only. Selects linear interpolation.

tecs.assets.ANIMATION_LINEAR: integer

tecs.assets.ANIMATION_ROTATION variable

Read-only. Selects a rotation animation channel.

tecs.assets.ANIMATION_ROTATION: integer

tecs.assets.ANIMATION_SCALE variable

Read-only. Selects a scale animation channel.

tecs.assets.ANIMATION_SCALE: integer

tecs.assets.ANIMATION_STEP variable

Read-only. Selects held-key interpolation.

tecs.assets.ANIMATION_STEP: integer

tecs.assets.ANIMATION_TRANSLATION variable

Read-only. Selects a translation animation channel.

tecs.assets.ANIMATION_TRANSLATION: integer

tecs.assets.ANIMATION_WEIGHTS variable

Read-only. Selects a morph-weight animation channel.

tecs.assets.ANIMATION_WEIGHTS: integer

tecs.assets.IMAGE_BC3 variable

Read-only. Selects a complete imported BC3 image mip chain.

tecs.assets.IMAGE_BC3: integer

tecs.assets.IMAGE_RGBA8 variable

Read-only. Selects decoded, uncompressed RGBA8 image storage.

tecs.assets.IMAGE_RGBA8: integer