Skip to content

Instantly share code, notes, and snippets.

@rparrett
Last active July 27, 2024 00:10
Show Gist options
  • Save rparrett/bb98a638d717f7f0b9be2b8ec24b6cb5 to your computer and use it in GitHub Desktop.
Save rparrett/bb98a638d717f7f0b9be2b8ec24b6cb5 to your computer and use it in GitHub Desktop.
Bevy 0.14: Modify a material in GLTF file after spawning it without changing other GLTFs
use bevy::{
color::palettes::basic,
prelude::*,
scene::{SceneInstance, SceneInstanceReady},
};
/// A marker component that we will add to the particular fox that we want to be red.
#[derive(Component)]
struct RedFox;
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn(PbrBundle {
mesh: meshes.add(Circle::new(4.0)),
material: materials.add(Color::WHITE),
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
..default()
});
commands.spawn((
SceneBundle {
scene: asset_server.load("models/animated/Fox.glb#Scene0"),
transform: Transform::from_scale(Vec3::splat(0.02)).with_translation(Vec3::NEG_X),
..default()
},
RedFox,
));
commands.spawn(SceneBundle {
scene: asset_server.load("models/animated/Fox.glb#Scene0"),
transform: Transform::from_scale(Vec3::splat(0.02)).with_translation(Vec3::X),
..default()
});
commands.spawn(PointLightBundle {
point_light: PointLight {
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(PostUpdate, decorate_red_fox)
.run();
}
fn decorate_red_fox(
mut events: EventReader<SceneInstanceReady>,
instances: Query<&SceneInstance, With<RedFox>>,
spawner: Res<SceneSpawner>,
mut material_query: Query<&mut Handle<StandardMaterial>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut red_material: Local<Option<Handle<StandardMaterial>>>,
) {
for event in events.read() {
let Ok(instance) = instances.get(event.parent) else {
continue;
};
for instance_entity in spawner.iter_instance_entities(**instance) {
let Ok(mut original_material) = material_query.get_mut(instance_entity) else {
continue;
};
let red_material = red_material.get_or_insert_with(|| {
let mut red = materials.get(&*original_material).unwrap().clone();
red.base_color = basic::RED.into();
materials.add(red)
});
*original_material = red_material.clone();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment