use bevy::prelude::*; use crate::{asset_tracking::LoadResource, audio::SoundEffect}; pub(super) fn plugin(app: &mut App) { app.register_type::(); app.load_resource::(); app.add_systems( Update, ( trigger_on_press, apply_interaction_palette, trigger_interaction_sound_effect, ) .run_if(resource_exists::), ); } /// Palette for widget interactions. Add this to an entity that supports /// [`Interaction`]s, such as a button, to change its [`BackgroundColor`] based /// on the current interaction state. #[derive(Component, Debug, Reflect)] #[reflect(Component)] pub struct InteractionPalette { pub none: Color, pub hovered: Color, pub pressed: Color, } /// Event triggered on a UI entity when the [`Interaction`] component on the same entity changes to /// [`Interaction::Pressed`]. Observe this event to detect e.g. button presses. #[derive(Event)] pub struct OnPress; fn trigger_on_press( interaction_query: Query<(Entity, &Interaction), Changed>, mut commands: Commands, ) { for (entity, interaction) in &interaction_query { if matches!(interaction, Interaction::Pressed) { commands.trigger_targets(OnPress, entity); } } } fn apply_interaction_palette( mut palette_query: Query< (&Interaction, &InteractionPalette, &mut BackgroundColor), Changed, >, ) { for (interaction, palette, mut background) in &mut palette_query { *background = match interaction { Interaction::None => palette.none, Interaction::Hovered => palette.hovered, Interaction::Pressed => palette.pressed, } .into(); } } #[derive(Resource, Asset, Reflect, Clone)] pub struct InteractionAssets { #[dependency] hover: Handle, #[dependency] press: Handle, } impl InteractionAssets { pub const PATH_BUTTON_HOVER: &'static str = "audio/sound_effects/button_hover.ogg"; pub const PATH_BUTTON_PRESS: &'static str = "audio/sound_effects/button_press.ogg"; } impl FromWorld for InteractionAssets { fn from_world(world: &mut World) -> Self { let assets = world.resource::(); Self { hover: assets.load(Self::PATH_BUTTON_HOVER), press: assets.load(Self::PATH_BUTTON_PRESS), } } } fn trigger_interaction_sound_effect( interaction_query: Query<&Interaction, Changed>, interaction_assets: Res, mut commands: Commands, ) { for interaction in &interaction_query { let source = match interaction { Interaction::Hovered => interaction_assets.hover.clone(), Interaction::Pressed => interaction_assets.press.clone(), _ => continue, }; commands.spawn(( AudioPlayer::(source), PlaybackSettings::DESPAWN, SoundEffect, )); } }