aevyrie / bevy_mod_picking

Picking and pointer events for Bevy.
https://crates.io/crates/bevy_mod_picking
Apache License 2.0
764 stars 170 forks source link

How to query all selected items? #311

Closed ddorstijn closed 6 months ago

ddorstijn commented 6 months ago

I would like to query all selected items. Is there a way to do this? I see there is a boolean value in the PickSelection component that says if this item is selected. But does this mean I have to query all the selectable items each frame? Only querying Changed settings would mean the system will only fire once.

StrikeForceZero commented 6 months ago

you can query Changed<PickSelection> and add a custom Selected marker to the entities when true, and remove it when false

use bevy::prelude::*;
use bevy_mod_picking::prelude::*;

pub struct SubPlugin;

impl Plugin for SubPlugin {
    fn build(&self, app: &mut App) {
        app
            .register_type::<Selected>()
            .add_systems(
                Update, 
                 (
                    update_selected,
                    print_selected,
                ).chain()
            )
        ;
    }
}

#[derive(Component, Debug, Clone, Reflect)]
pub struct Selected;

fn update_selected(
    mut commands: Commands,
    query: Query<(Entity, &PickSelection), Changed<PickSelection>>
) {
    for (entity, selection) in query.iter() {
        if selection.is_selected {
            commands.entity(entity).insert(Selected);
        } else {
            commands.entity(entity).remove::<Selected>();
        }
    }
}

fn print_selected(
    query: Query<Entity, With<Selected>>,
) {
    for entity in query.iter() {
        info!("{entity:?}");        
    }
}
aevyrie commented 6 months ago

The above suggestion is a good solution. The reason we don't have a tag component by default is that archetype changes can be expensive. Instead, we toggle a boolean and leave it up to the user if they want to attach their own tag on change.