Skip to content

atlas

stable

Texture atlas management for 2D graphics — store, query, pack, and compute UV coordinates for sprite regions.

use plugin atlas::{TextureAtlas.new, add_region, get_region, …}
16 functions Utilities
/ filter jk navigate Esc clear
Functions (16)
  1. TextureAtlas.new Create a new texture atlas
  2. add_region Register a named sprite region
  3. get_region Look up a region by name
  4. remove_region Remove a named region
  5. regions List all regions with coordinates
  6. contains Check if a region name exists
  7. width Get the atlas width in pixels
  8. height Get the atlas height in pixels
  9. get_uv Compute normalized UV coordinates
  10. find_by_prefix Find all regions matching a prefix
  11. count Return the number of regions
  12. clear Remove all regions
  13. resize Change atlas dimensions
  14. info Get width, height, and region count
  15. pack Auto-pack items using shelf algorithm
  16. rename_region Rename an existing region

Overview

The atlas plugin manages a texture atlas: a single large texture subdivided into named rectangular regions, the standard way 2D engines pack many sprites into one GPU texture. Each atlas is a stateful handle returned by TextureAtlas.new(width, height); you call methods on it to register regions, query them, and compute the normalized UV coordinates a shader needs to sample a sprite. Pixel coordinates stay in image space, while get_uv divides them by the atlas dimensions to produce floats in [0, 1].

Reach for it whenever you have many small images that should live in one texture: sprite sheets, animation frames, tilesets, or UI icons. You can place regions manually with add_region, or hand a batch of sizes to pack and let the shelf bin-packing algorithm assign coordinates for you. Region names are arbitrary strings, so prefix conventions like walk_0, walk_1 pair naturally with find_by_prefix to gather animation frames.

Common patterns

Pack a sprite sheet and read back UVs

Let the atlas place a batch of sprites, then fetch UV coordinates for the GPU.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(256, 256)
let placed = atlas.pack([
  #{"name": "hero", "w": 64, "h": 64},
  #{"name": "coin", "w": 32, "h": 32},
  #{"name": "gem",  "w": 32, "h": 32}
])

print("packed {atlas.count()} sprites")
let uv = atlas.get_uv("hero")
print("hero uv: ({uv["u0"]}, {uv["v0"]}) -> ({uv["u1"]}, {uv["v1"]})")

Drive an animation from prefixed frames

Register frames with a shared prefix, then collect them as a sequence.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 64)
atlas.add_region("walk_0", 0, 0, 64, 64)
atlas.add_region("walk_1", 64, 0, 64, 64)
atlas.add_region("walk_2", 128, 0, 64, 64)

let frames = atlas.find_by_prefix("walk_")
print("walk cycle has {frames.len()} frames")
for frame in frames {
  print("frame {frame["name"]} at x={frame["x"]}")
}

Rebuild an atlas in place

Clear stale regions and re-pack at a new size without allocating a new handle.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(128, 128)
atlas.add_region("old", 0, 0, 32, 32)

atlas.clear()
atlas.resize(256, 256)
atlas.add_region("fresh", 0, 0, 64, 64)

let info = atlas.info()
print("atlas {info["width"]}x{info["height"]}, {info["count"]} regions")

Create a new texture atlas

Creates a new texture atlas with the given pixel dimensions. The atlas stores named rectangular regions and can compute UV coordinates for use in shaders.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(1024, 1024)
atlas.add_region("player_idle", 0, 0, 64, 64)
atlas.add_region("player_run", 64, 0, 64, 64)
print(atlas.count())

Register a named sprite region

Registers a named sprite region with pixel coordinates (x, y) and size (w, h). If a region with the same name already exists, it is replaced.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 512)
atlas.add_region("coin", 0, 0, 32, 32)
atlas.add_region("gem", 32, 0, 32, 32)

Look up a region by name

Returns a table with x, y, w, h fields for the named region, or nil if the name is not registered.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 512)
atlas.add_region("player", 0, 0, 64, 64)
let r = atlas.get_region("player")
print("x={r["x"]} y={r["y"]} w={r["w"]} h={r["h"]}")

Remove a named region

Removes the named region. Returns true if the region existed and was removed, false if it was not found.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 512)
atlas.add_region("temp", 0, 0, 16, 16)
print(atlas.remove_region("temp"))
print(atlas.remove_region("temp"))

List all regions with coordinates

Returns a list of all regions. Each entry is a table with name, x, y, w, h fields.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 512)
atlas.add_region("a", 0, 0, 32, 32)
atlas.add_region("b", 32, 0, 32, 32)
let all = atlas.regions()
print(all[0]["name"])

Check if a region name exists

Returns true if a region with the given name is registered in the atlas.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(256, 256)
atlas.add_region("icon", 0, 0, 16, 16)
print(atlas.contains("icon"))
print(atlas.contains("missing"))

Get the atlas width in pixels

Returns the atlas width in pixels as set at construction or after resize.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(1024, 512)
print(atlas.width())

Get the atlas height in pixels

Returns the atlas height in pixels.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(1024, 512)
print(atlas.height())

Compute normalized UV coordinates

Computes normalized UV coordinates for the named region. Returns a table with u0, v0, u1, v1 as floats in [0, 1], suitable for GPU texture sampling. Returns nil if the region is not found.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 512)
atlas.add_region("hero", 0, 0, 64, 64)
let uv = atlas.get_uv("hero")
print("u0={uv["u0"]} v0={uv["v0"]} u1={uv["u1"]} v1={uv["v1"]}")

Because UVs are computed from the current atlas dimensions, the same region yields different coordinates after a resize:

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(64, 64)
atlas.add_region("tile", 0, 0, 64, 64)
print(atlas.get_uv("tile")["u1"])

atlas.resize(128, 128)
print(atlas.get_uv("tile")["u1"])

Find all regions matching a prefix

Returns all regions whose names start with prefix. Each entry has name, x, y, w, h. Useful for finding all frames of an animation (e.g. "walk_").

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 256)
atlas.add_region("walk_0", 0, 0, 32, 32)
atlas.add_region("walk_1", 32, 0, 32, 32)
atlas.add_region("idle_0", 64, 0, 32, 32)

let frames = atlas.find_by_prefix("walk_")
print(frames[0]["name"])

Pair it with count to confirm a prefix matched the expected number of frames before driving an animation:

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(512, 256)
atlas.add_region("run_0", 0, 0, 32, 32)
atlas.add_region("run_1", 32, 0, 32, 32)
atlas.add_region("jump_0", 64, 0, 32, 32)

let run = atlas.find_by_prefix("run_")
print("{run.len()} run frames of {atlas.count()} total")

Return the number of regions

Returns the number of regions currently registered.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(256, 256)
atlas.add_region("a", 0, 0, 16, 16)
atlas.add_region("b", 16, 0, 16, 16)
print(atlas.count())

Remove all regions

Removes all registered regions from the atlas. The atlas dimensions are unchanged.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(256, 256)
atlas.add_region("sprite", 0, 0, 32, 32)
atlas.clear()
print(atlas.count())

Change atlas dimensions

Updates the atlas pixel dimensions. Existing region pixel coordinates are not changed, but UV values will differ after a resize.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(256, 256)
atlas.resize(512, 512)
print(atlas.width())

Get width, height, and region count

Returns a summary table with width, height, and count fields.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(1024, 1024)
atlas.add_region("icon", 0, 0, 32, 32)
let info = atlas.info()
print("atlas {info["width"]}x{info["height"]}, {info["count"]} regions")

Auto-pack items using shelf algorithm

Auto-packs a list of {name, w, h} entries into the atlas using a shelf (row-based) bin-packing algorithm. Items are sorted by height descending for better fit. Returns the list of placed regions with their assigned coordinates. Errors if items do not fit.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(256, 256)
let items = [
  #{"name": "hero", "w": 64, "h": 64},
  #{"name": "coin", "w": 32, "h": 32},
  #{"name": "gem",  "w": 32, "h": 32}
]
let placed = atlas.pack(items)
print(placed[0]["name"])
print(atlas.count())

Packing can overflow when the items exceed the atlas area; size the atlas generously or pack in batches:

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(64, 64)
let tiles = [
  #{"name": "a", "w": 48, "h": 48},
  #{"name": "b", "w": 48, "h": 48}
]
let placed = atlas.pack(tiles)
for p in placed {
  print("{p["name"]} -> ({p["x"]}, {p["y"]})")
}

Rename an existing region

Renames an existing region. Returns true on success, false if old_name was not found.

use plugin atlas::{TextureAtlas}

let atlas = TextureAtlas.new(256, 256)
atlas.add_region("tmp_sprite", 0, 0, 32, 32)
atlas.rename_region("tmp_sprite", "player_idle")
print(atlas.contains("player_idle"))
enespt-br