use bevy::{ gltf::GltfMaterialName, pbr::{ExtendedMaterial, MaterialExtension}, prelude::*, render::render_resource::AsBindGroup, shader::ShaderRef, world_serialization::WorldInstanceReady, }; pub type FighterMaterial = ExtendedMaterial; #[derive(Component)] pub struct FighterMesh { pub fighter: Entity, } #[derive(Asset, AsBindGroup, Reflect, Debug, Clone, Default)] pub struct FighterMaterialExtension { #[uniform(100)] status_color: LinearRgba, #[uniform(100)] status_color_intensity: f32, } const SHADER_ASSET_PATH: &str = "embedded://shinespark/shaders/fighter.wgsl"; impl FighterMaterialExtension { pub fn new(status_color: Color) -> Self { Self { status_color: status_color.into(), status_color_intensity: 0.0, ..default() } } pub fn update_status_color(&mut self, status_color: LinearRgba, intensity: f32) { self.status_color = status_color; self.status_color_intensity = intensity; } } impl MaterialExtension for FighterMaterialExtension { fn fragment_shader() -> ShaderRef { SHADER_ASSET_PATH.into() } fn deferred_fragment_shader() -> ShaderRef { SHADER_ASSET_PATH.into() } } pub fn bind_fighter_material( scene_ready: On, mut commands: Commands, children: Query<&Children>, //color_override: Query<&ColorOverride>, mesh_materials: Query<(Entity, &MeshMaterial3d, &GltfMaterialName)>, mut asset_materials: ResMut>, original_materials: Res>, ) { for descendant in children.iter_descendants(scene_ready.entity) { let Ok((entity, id, material_name)) = mesh_materials.get(descendant) else { continue; }; if !material_name.starts_with("Fighter_") { continue; } let Some(original_material) = original_materials.get(id.id()) else { continue; }; commands .entity(entity) .remove::>() .insert(( MeshMaterial3d(asset_materials.add(ExtendedMaterial { base: StandardMaterial { // can be used in forward or deferred mode ..original_material.clone() }, extension: FighterMaterialExtension::new( bevy::color::palettes::css::BLUE.into(), ), })), FighterMesh { fighter: scene_ready.entity, }, )); } }