Skip to content
Plugins (183)

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
Runs with the native Zolo host

Plugin snippets can be edited in the Playground, but native capabilities are executed locally with the Zolo CLI.

/ 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

From import to result

  1. 01Import only what you use
  2. 02Copy the smallest example
  3. 03Run it with the Zolo CLI

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"))

Global index

Find your way through Zolo

Try an idea

Start here

9 results

9 results

en