use bevy::{
app::{App, PluginGroup, Startup},
asset::{AssetServer, Assets},
audio::AudioPlugin,
color::{palettes, Color},
gltf::GltfAssetLabel,
math::{Dir3, Vec3},
pbr::{DirectionalLight, MeshMaterial3d, StandardMaterial},
prelude::{Camera3d, Children, Commands, Component, Query, Res, ResMut, Transform, Trigger},
scene::{SceneInstanceReady, SceneRoot},
DefaultPlugins,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins.build().disable::<AudioPlugin>())
.add_systems(Startup, setup_scene)
.add_observer(change_material)
.run();
}
#[derive(Component)]
struct ColorOverride(Color);
fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn((
Camera3d::default(),
Transform::from_xyz(0., 1., 2.5).looking_at(Vec3::new(0., 0.25, 0.), Dir3::Y),
));
commands.spawn((
DirectionalLight::default(),
Transform::from_xyz(0., 1., 0.25).looking_at(Vec3::ZERO, Dir3::Y),
));
let flight_helmet = asset_server
.load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf"));
commands.spawn(SceneRoot(flight_helmet.clone()));
commands.spawn((
SceneRoot(flight_helmet.clone()),
Transform::from_xyz(-1.25, 0., 0.),
ColorOverride(palettes::tailwind::RED_300.into()),
));
commands.spawn((
SceneRoot(flight_helmet),
Transform::from_xyz(1.25, 0., 0.),
ColorOverride(palettes::tailwind::GREEN_300.into()),
));
}
fn change_material(
trigger: Trigger<SceneInstanceReady>,
mut commands: Commands,
children: Query<&Children>,
color_override: Query<&ColorOverride>,
mesh_materials: Query<&MeshMaterial3d<StandardMaterial>>,
mut asset_materials: ResMut<Assets<StandardMaterial>>,
) {
let Ok(color_override) = color_override.get(trigger.target()) else {
return;
};
for descendants in children.iter_descendants(trigger.target()) {
if let Some(material) = mesh_materials
.get(descendants)
.ok()
.and_then(|id| asset_materials.get_mut(id.id()))
{
let mut new_material = material.clone();
new_material.base_color = color_override.0;
commands
.entity(descendants)
.insert(MeshMaterial3d(asset_materials.add(new_material)));
}
}
}