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(&self, bank_id: usize, read: impl FnOnce(&GlyphBank) -> R) -> Option; /// 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(&self, bank_id: usize, read: impl FnOnce(&SceneBank) -> R) -> Option; /// 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>, scene_banks: Vec>, } impl RenderResourceAccess for TestRenderResources { fn with_glyph_bank( &self, bank_id: usize, read: impl FnOnce(&GlyphBank) -> R, ) -> Option { self.glyph_banks.get(bank_id)?.as_ref().map(read) } fn glyph_bank_count(&self) -> usize { self.glyph_banks.len() } fn with_scene_bank( &self, bank_id: usize, read: impl FnOnce(&SceneBank) -> R, ) -> Option { 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); } }