Skip to main content

lunar_render/
atlas.rs

1//! texture atlas integration for the render system.
2#![allow(clippy::missing_errors_doc, clippy::must_use_candidate)]
3//!
4//! provides [`TextureAtlas`] resource that wraps a packed atlas texture
5//! with named region lookup. sprites can reference atlas regions via
6//! `DrawKind::Sprite` with an optional `atlas_region` field.
7//!
8//! # example
9//!
10//! ```ignore
11//! use lunar_render::atlas::TextureAtlas;
12//! use lunar_atlas::{AtlasManifest, AtlasRegion};
13//!
14//! // load atlas texture via asset server
15//! let atlas_texture = asset_server.load_texture("sprites_atlas.li");
16//! let manifest = AtlasManifest::from_bytes(&manifest_bytes)?;
17//!
18//! let texture_atlas = TextureAtlas::new(atlas_texture, manifest);
19//! let region = texture_atlas.region("player_idle");
20//! ```
21
22use lunar_assets::Handle;
23use lunar_assets::Texture;
24use lunar_atlas::{AtlasManifest, AtlasRegion};
25
26/// a loaded texture atlas with GPU texture handle and region lookup.
27pub struct TextureAtlas {
28	/// handle to the atlas GPU texture
29	pub texture: Handle<Texture>,
30	/// manifest describing region layout
31	pub manifest: AtlasManifest,
32	/// pre-computed UV regions for fast lookup
33	regions: rustc_hash::FxHashMap<String, AtlasRegion>,
34}
35
36impl TextureAtlas {
37	/// create a new texture atlas from a loaded texture and manifest.
38	#[must_use]
39	pub fn new(texture: Handle<Texture>, manifest: AtlasManifest) -> Self {
40		let regions = manifest.resolve_regions();
41		Self {
42			texture,
43			manifest,
44			regions,
45		}
46	}
47
48	/// look up a region by name.
49	///
50	/// returns the [`AtlasRegion`] with UV coordinates for this sprite.
51	/// # Panics
52	///
53	/// panics if the region does not exist.
54	#[must_use]
55	pub fn region(&self, name: &str) -> &AtlasRegion {
56		self.regions
57			.get(name)
58			.unwrap_or_else(|| panic!("atlas region '{name}' not found"))
59	}
60
61	/// look up a region by name, returning None if not found.
62	#[must_use]
63	pub fn try_region(&self, name: &str) -> Option<&AtlasRegion> {
64		self.regions.get(name)
65	}
66
67	/// get the atlas texture handle.
68	#[must_use]
69	pub const fn texture_handle(&self) -> &Handle<Texture> {
70		&self.texture
71	}
72
73	/// get all region names.
74	pub fn region_names(&self) -> impl Iterator<Item = &String> {
75		self.regions.keys()
76	}
77}