use std::f32::consts::{PI, TAU}; use bevy::{gltf::GltfPlugin, prelude::*, scene::SceneInstance}; use bevy_mod_outline::{ AsyncSceneInheritOutline, AsyncSceneInheritOutlinePlugin, OutlineBundle, OutlinePlugin, OutlineStencil, OutlineVolume, ATTRIBUTE_OUTLINE_NORMAL, }; fn main() { App::new() // Register outline normal vertex attribute with glTF plugin .add_plugins( DefaultPlugins.build().set( GltfPlugin::default() .add_custom_vertex_attribute("_OUTLINE_NORMAL", ATTRIBUTE_OUTLINE_NORMAL), ), ) .add_plugins((OutlinePlugin, AsyncSceneInheritOutlinePlugin)) .insert_resource(AmbientLight::default()) .add_systems(Startup, setup) .add_systems( Update, (setup_scene_once_loaded, rotates_and_pulses, rotates_hue), ) .run(); } #[derive(Component)] struct RotatesAndPulses; #[derive(Component)] struct RotatesHue; fn setup(mut commands: Commands, asset_server: Res) { // Camera commands.spawn(Camera3dBundle { transform: Transform::from_xyz(20.0, 20.0, 30.0) .looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y), ..default() }); // Light commands.spawn(DirectionalLightBundle { transform: Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)), directional_light: DirectionalLight { shadows_enabled: true, ..default() }, ..default() }); // Hollow commands .spawn(SceneBundle { scene: asset_server.load("hollow.glb#Scene0"), ..default() }) .insert(RotatesAndPulses) .insert(OutlineBundle { outline: OutlineVolume { visible: true, width: 0.0, colour: Color::srgb(0.0, 0.0, 1.0), }, stencil: OutlineStencil { enabled: true, offset: 0.0, }, ..default() }) .insert(AsyncSceneInheritOutline); } // Once the scene is loaded, start the animation and add an outline fn setup_scene_once_loaded( mut commands: Commands, scene_query: Query<&SceneInstance>, scene_manager: Res, name_query: Query<&Name, With>>, mut done: Local, ) { if !*done { if let Ok(scene) = scene_query.get_single() { if scene_manager.instance_is_ready(**scene) { for entity in scene_manager.iter_instance_entities(**scene) { if let Ok(name) = name_query.get(entity) { if name.as_str() == "inside" { commands.entity(entity).insert(RotatesHue); } } } *done = true; } } } } fn rotates_and_pulses( mut query: Query<(&mut Transform, &mut OutlineVolume), With>, timer: Res