use bevy::platform::collections::{HashMap, HashSet};
use bevy::prelude::{Handle, Resource, Scene, StandardMaterial};
#[derive(Resource, Default)]
pub struct ShapeRegistry {
meshes: HashMap<String, Handle<Scene>>,
materials: HashMap<String, Handle<StandardMaterial>>,
pub default_material: Option<Handle<StandardMaterial>>,
stretch_uv_materials: HashSet<String>,
stretch_uv_meshes: HashSet<String>,
}
impl ShapeRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register_mesh(&mut self, id: impl Into<String>, handle: Handle<Scene>) {
self.meshes.insert(id.into(), handle);
}
pub fn register_material(&mut self, id: impl Into<String>, handle: Handle<StandardMaterial>) {
self.materials.insert(id.into(), handle);
}
pub fn register_stretch_material(&mut self, id: impl Into<String>) {
self.stretch_uv_materials.insert(id.into());
}
pub fn register_stretch_mesh(&mut self, id: impl Into<String>) {
self.stretch_uv_meshes.insert(id.into());
}
pub fn should_stretch_uvs(&self, mesh_id: &str, mat_id: Option<&str>) -> bool {
self.stretch_uv_meshes.contains(mesh_id)
|| mat_id.is_some_and(|m| self.stretch_uv_materials.contains(m))
}
pub fn get_mesh(&self, id: &str) -> Option<&Handle<Scene>> {
self.meshes.get(id)
}
pub fn resolve_material(&self, id: Option<&str>) -> Option<Handle<StandardMaterial>> {
if let Some(h) = id.and_then(|name| self.materials.get(name)) {
return Some(h.clone());
}
self.default_material.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
use bevy::prelude::*;
fn make_app() -> App {
let mut app = App::new();
app.add_plugins(bevy::asset::AssetPlugin::default());
app
}
#[test]
fn register_and_retrieve_mesh() {
let mut app = make_app();
app.init_resource::<Assets<Scene>>();
let world = app.world_mut();
let mut scenes = world.resource_mut::<Assets<Scene>>();
let handle: Handle<Scene> = scenes.add(Scene::new(World::new()));
let mut registry = ShapeRegistry::new();
registry.register_mesh("Window", handle.clone());
assert!(registry.get_mesh("Window").is_some());
assert!(registry.get_mesh("Door").is_none());
}
#[test]
fn resolve_material_falls_back_to_default() {
let mut app = make_app();
app.init_resource::<Assets<StandardMaterial>>();
let world = app.world_mut();
let mut mats = world.resource_mut::<Assets<StandardMaterial>>();
let default_mat: Handle<StandardMaterial> = mats.add(StandardMaterial::default());
let mut registry = ShapeRegistry::new();
registry.default_material = Some(default_mat.clone());
let resolved = registry.resolve_material(Some("Brick"));
assert!(resolved.is_some());
let resolved2 = registry.resolve_material(None);
assert!(resolved2.is_some());
}
#[test]
fn resolve_material_returns_registered_handle() {
let mut app = make_app();
app.init_resource::<Assets<StandardMaterial>>();
let world = app.world_mut();
let mut mats = world.resource_mut::<Assets<StandardMaterial>>();
let brick: Handle<StandardMaterial> = mats.add(StandardMaterial {
base_color: bevy::color::Color::srgb(0.8, 0.4, 0.2),
..Default::default()
});
let default_mat: Handle<StandardMaterial> = mats.add(StandardMaterial::default());
let mut registry = ShapeRegistry::new();
registry.register_material("Brick", brick.clone());
registry.default_material = Some(default_mat);
let resolved = registry.resolve_material(Some("Brick"));
assert!(resolved.is_some());
assert_eq!(resolved.unwrap().id(), brick.id());
}
}