Python API & batch
The packing engine is pure Python — no bpy, no scene, no UI — so you can pack from scripts and process entire .blend libraries headless.
The core call
Packer.pack_islands() takes a list of UVIsland and a PackConfig and returns a PackResult:
from src.core.packer import Packer
from src.core.types import AABB, PackConfig, UVIsland
def make_island(x, y, w, h, idx):
uvs = [(x, y), (x + w, y), (x + w, y + h), (x, y + h)]
return UVIsland(
polygons=[idx], uvs=uvs,
bbox=AABB(x, y, x + w, y + h),
area=w * h, aspect_ratio=w / h,
source_object=f"object_{idx}",
)
islands = [make_island(0.0, 0.0, 0.3, 0.2, i) for i in range(6)]
config = PackConfig(
atlas_size=(1024, 1024),
margin=0.005,
algorithm="maxrects",
allow_rotation=True,
selected_only=False,
normalize=True,
)
result = Packer().pack_islands(islands, config)
print(f"Efficiency: {result.efficiency:.1%}, {result.islands_packed} islands")
Reading the result
Each IslandPlacement describes the final transform of one island:
p = result.placements[0]
p.position # lower-left corner of the placed bbox, UV space
p.rotation # degrees, counter-clockwise
p.scale # global scale applied by the packer
p.udim_tile # 0 = tile 1001, 1 = 1002, ...
p.placed_bbox # final axis-aligned bounding box
The transform mapping an original UV (u, v) to the atlas: rotate by rotation around the origin, scale by scale * texel_density_scale, then translate so the rotated bounding box's lower-left corner lands on position (plus the UDIM tile offset) — the same transform applied to the mesh inside Blender.
Advanced config fields
Stacking, locking, grouping and destination are plain PackConfig fields:
config = PackConfig(
atlas_size=(2048, 2048), margin=0.002, algorithm="maxrects",
allow_rotation=True, selected_only=False, normalize=True,
stack_similar=True, # identical islands share one slot
lock_overlapping=True, # intentional stacks move as one group
group_by="material", # one UDIM tile per material
pack_to_tile=0, # target UDIM tile (0 = 1001)
pack_to_region=None, # or AABB(0.5, 0.5, 1.0, 1.0) for a sub-region
)
Progress callbacks
def on_progress(step, total, message):
print(f"{step}/{total} — {message}")
Packer().pack_islands(islands, config, progress_callback=on_progress)
Headless batch processing
Use scripts/batch_pack.py to pack whole libraries of .blend files from the command line:
blender --background --factory-startup \
--python scripts/batch_pack.py -- \
--input-dir ./assets --output-dir ./packed
The worker uses the repository via sys.path and does not require the add-on to be installed.
The full API reference (every field of PackConfig, UVIsland, IslandPlacement and PackResult) ships with the source in docs/api/. The code blocks above are executed as part of the test suite, so they stay correct release to release.