2026-06-15 16:04:36 +01:00

110 lines
3.6 KiB
Rust

use crate::glyph_bank::GlyphBank;
use crate::scene_bank::SceneBank;
/// Read-only render resource lookup used by render backends.
///
/// Resource ids are stable bank slots carried by render submissions. The
/// callback shape keeps bank ownership inside the provider while exposing only
/// borrowed read access to the caller.
pub trait RenderResourceAccess {
/// Reads a resident glyph bank by id.
fn with_glyph_bank<R>(&self, bank_id: usize, read: impl FnOnce(&GlyphBank) -> R) -> Option<R>;
/// Returns the number of glyph bank ids accepted by this provider.
fn glyph_bank_count(&self) -> usize;
/// Reads a resident scene bank by id.
fn with_scene_bank<R>(&self, bank_id: usize, read: impl FnOnce(&SceneBank) -> R) -> Option<R>;
/// Returns the number of scene bank ids accepted by this provider.
fn scene_bank_count(&self) -> usize;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::glyph::Glyph;
use crate::glyph_bank::TileSize;
use crate::scene_layer::{ParallaxFactor, SceneLayer};
use crate::tile::Tile;
use crate::tilemap::TileMap;
struct TestRenderResources {
glyph_banks: Vec<Option<GlyphBank>>,
scene_banks: Vec<Option<SceneBank>>,
}
impl RenderResourceAccess for TestRenderResources {
fn with_glyph_bank<R>(
&self,
bank_id: usize,
read: impl FnOnce(&GlyphBank) -> R,
) -> Option<R> {
self.glyph_banks.get(bank_id)?.as_ref().map(read)
}
fn glyph_bank_count(&self) -> usize {
self.glyph_banks.len()
}
fn with_scene_bank<R>(
&self,
bank_id: usize,
read: impl FnOnce(&SceneBank) -> R,
) -> Option<R> {
self.scene_banks.get(bank_id)?.as_ref().map(read)
}
fn scene_bank_count(&self) -> usize {
self.scene_banks.len()
}
}
fn scene_bank(tile_size: TileSize) -> SceneBank {
let layer = SceneLayer {
active: true,
glyph_asset_id: 7,
tile_size,
parallax_factor: ParallaxFactor { x: 1.0, y: 1.0 },
tilemap: TileMap {
width: 1,
height: 1,
tiles: vec![Tile {
active: true,
glyph: Glyph { glyph_id: 3, palette_id: 0 },
flip_x: false,
flip_y: false,
}],
},
};
SceneBank { layers: std::array::from_fn(|_| layer.clone()) }
}
#[test]
fn reads_resident_resources_by_id() {
let resources = TestRenderResources {
glyph_banks: vec![None, Some(GlyphBank::new(TileSize::Size16, 16, 16)), None],
scene_banks: vec![Some(scene_bank(TileSize::Size8)), None],
};
assert_eq!(resources.glyph_bank_count(), 3);
assert_eq!(resources.scene_bank_count(), 2);
assert_eq!(resources.with_glyph_bank(1, |bank| bank.tile_size), Some(TileSize::Size16));
assert_eq!(
resources.with_scene_bank(0, |bank| bank.layers[0].tile_size),
Some(TileSize::Size8)
);
}
#[test]
fn missing_resources_return_none() {
let resources = TestRenderResources { glyph_banks: vec![None], scene_banks: vec![None] };
assert_eq!(resources.with_glyph_bank(0, |bank| bank.width), None);
assert_eq!(resources.with_glyph_bank(9, |bank| bank.width), None);
assert_eq!(resources.with_scene_bank(0, |bank| bank.layers[0].active), None);
assert_eq!(resources.with_scene_bank(9, |bank| bank.layers[0].active), None);
}
}