use bevy::prelude::*;
pub struct SelectionPlugin;
impl Plugin for SelectionPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(Selection::default())
.add_observer(on_selected_removed);
}
}
#[derive(Component)]
pub struct Selected;
#[derive(Resource, Default)]
pub struct Selection {
pub entities: Vec<Entity>,
}
impl Selection {
pub fn select_single(&mut self, commands: &mut Commands, entity: Entity) {
for &e in &self.entities {
if e != entity {
if let Ok(mut ec) = commands.get_entity(e) {
ec.remove::<Selected>();
}
}
}
self.entities.clear();
self.entities.push(entity);
if let Ok(mut ec) = commands.get_entity(entity) {
ec.insert(Selected);
}
}
pub fn toggle(&mut self, commands: &mut Commands, entity: Entity) {
if let Some(pos) = self.entities.iter().position(|&e| e == entity) {
self.entities.remove(pos);
if let Ok(mut ec) = commands.get_entity(entity) {
ec.remove::<Selected>();
}
} else {
self.entities.push(entity);
if let Ok(mut ec) = commands.get_entity(entity) {
ec.insert(Selected);
}
}
}
pub fn extend(&mut self, commands: &mut Commands, entity: Entity) {
if !self.entities.contains(&entity) {
self.entities.push(entity);
if let Ok(mut ec) = commands.get_entity(entity) {
ec.insert(Selected);
}
}
}
pub fn clear(&mut self, commands: &mut Commands) {
for &e in &self.entities {
if let Ok(mut ec) = commands.get_entity(e) {
ec.remove::<Selected>();
}
}
self.entities.clear();
}
pub fn select_multiple(&mut self, commands: &mut Commands, entities: &[Entity]) {
self.clear(commands);
for &entity in entities {
self.entities.push(entity);
if let Ok(mut ec) = commands.get_entity(entity) {
ec.insert(Selected);
}
}
}
pub fn primary(&self) -> Option<Entity> {
self.entities.last().copied()
}
pub fn is_selected(&self, entity: Entity) -> bool {
self.entities.contains(&entity)
}
}
fn on_selected_removed(trigger: On<Remove, Selected>, mut selection: ResMut<Selection>) {
let entity = trigger.event_target();
selection.entities.retain(|&e| e != entity);
}