use bevy::prelude::*;
use brkrs::systems::textures::loader::{ObjectClass, TextureManifest, TypeVariantDefinition};
use brkrs::systems::textures::{
FallbackRegistry, ProfileMaterialBank, TextureMaterialsPlugin, TypeVariantRegistry,
};
use brkrs::systems::textures::loader::RawTextureManifest as DiskTextureManifest;
use std::fs;
fn app_with_variant_registry() -> App {
let mut app = App::new();
app.add_plugins(MinimalPlugins);
app.insert_resource(Assets::<StandardMaterial>::default());
app.add_plugins(TextureMaterialsPlugin);
app.update();
app
}
#[test]
fn disk_manifest_populates_registry_for_new_bricks() {
let mut app = app_with_variant_registry();
let (handle_a, handle_b) = {
let mut materials = app.world_mut().resource_mut::<Assets<StandardMaterial>>();
(
materials.add(StandardMaterial {
base_color: Color::srgba(0.5, 0.5, 0.5, 1.0),
unlit: true,
..default()
}),
materials.add(StandardMaterial {
base_color: Color::srgba(0.9, 0.2, 0.2, 1.0),
unlit: true,
..default()
}),
)
};
{
let mut bank = app.world_mut().resource_mut::<ProfileMaterialBank>();
bank.insert_for_tests("brick/type20", handle_a.clone());
bank.insert_for_tests("brick/indestructible", handle_b.clone());
}
let contents = fs::read_to_string("assets/textures/manifest.ron").expect("read manifest");
let raw_manifest: DiskTextureManifest =
ron::de::from_str(&contents).expect("parse manifest ron");
let manifest = brkrs::systems::textures::loader::TextureManifest::from_raw(raw_manifest);
{
let world = app.world_mut();
world.resource_scope(|world, mut registry: Mut<TypeVariantRegistry>| {
world.resource_scope(|world, bank: Mut<ProfileMaterialBank>| {
world.resource_scope(|_world, mut fallback: Mut<FallbackRegistry>| {
registry.rebuild(&manifest, &bank, &mut fallback);
});
});
});
}
let reg = app.world().resource::<TypeVariantRegistry>();
assert_eq!(
reg.get(brkrs::systems::textures::loader::ObjectClass::Brick, 20)
.unwrap(),
handle_a
);
assert_eq!(
reg.get(brkrs::systems::textures::loader::ObjectClass::Brick, 90)
.unwrap(),
handle_b
);
}
#[test]
fn immediate_spawn_registry_populated_from_manifest() {
let mut app = app_with_variant_registry();
let handle_1 = {
let mut materials = app.world_mut().resource_mut::<Assets<StandardMaterial>>();
materials.add(StandardMaterial {
base_color: Color::srgba(1.0, 0.0, 0.0, 1.0),
unlit: true,
..default()
})
};
{
let mut bank = app.world_mut().resource_mut::<ProfileMaterialBank>();
bank.insert_for_tests("ball/default", handle_1.clone());
}
let manifest = TextureManifest {
profiles: Default::default(),
type_variants: vec![TypeVariantDefinition {
object_class: ObjectClass::Ball,
type_id: 7,
profile_id: "ball/default".to_string(),
emissive_color: None,
animation: None,
}],
level_overrides: Default::default(),
level_switch: None,
};
{
let world = app.world_mut();
world.resource_scope(|world, mut registry: Mut<TypeVariantRegistry>| {
world.resource_scope(|world, bank: Mut<ProfileMaterialBank>| {
world.resource_scope(|_world, mut fallback: Mut<FallbackRegistry>| {
registry.rebuild(&manifest, &bank, &mut fallback);
});
});
});
}
let registry = app.world().resource::<TypeVariantRegistry>();
let got = registry.get(ObjectClass::Ball, 7);
assert!(got.is_some());
assert_eq!(got.unwrap(), handle_1);
}
#[test]
fn runtime_mutation_updates_registry_mapping() {
let mut app = app_with_variant_registry();
let (handle_a, handle_b) = {
let mut materials = app.world_mut().resource_mut::<Assets<StandardMaterial>>();
let a = materials.add(StandardMaterial {
base_color: Color::srgba(0.1, 0.2, 0.3, 1.0),
unlit: true,
..default()
});
let b = materials.add(StandardMaterial {
base_color: Color::srgba(0.9, 0.8, 0.7, 1.0),
unlit: true,
..default()
});
(a, b)
};
{
let mut bank = app.world_mut().resource_mut::<ProfileMaterialBank>();
bank.insert_for_tests("ball/default", handle_a.clone());
}
let manifest = TextureManifest {
profiles: Default::default(),
type_variants: vec![TypeVariantDefinition {
object_class: ObjectClass::Ball,
type_id: 2,
profile_id: "ball/default".to_string(),
emissive_color: None,
animation: None,
}],
level_overrides: Default::default(),
level_switch: None,
};
{
let world = app.world_mut();
world.resource_scope(|world, mut registry: Mut<TypeVariantRegistry>| {
world.resource_scope(|world, bank: Mut<ProfileMaterialBank>| {
world.resource_scope(|_world, mut fallback: Mut<FallbackRegistry>| {
registry.rebuild(&manifest, &bank, &mut fallback);
});
});
});
}
{
let registry = app.world().resource::<TypeVariantRegistry>();
assert_eq!(registry.get(ObjectClass::Ball, 2).unwrap(), handle_a);
}
{
let mut bank = app.world_mut().resource_mut::<ProfileMaterialBank>();
bank.insert_for_tests("ball/default", handle_b.clone());
}
{
let world = app.world_mut();
world.resource_scope(|world, mut registry: Mut<TypeVariantRegistry>| {
world.resource_scope(|world, bank: Mut<ProfileMaterialBank>| {
world.resource_scope(|_world, mut fallback: Mut<FallbackRegistry>| {
registry.rebuild(&manifest, &bank, &mut fallback);
});
});
});
}
let registry = app.world().resource::<TypeVariantRegistry>();
assert_eq!(registry.get(ObjectClass::Ball, 2).unwrap(), handle_b);
}