From d8b3d078b4ceb82f69fccf590ae337903a04de6d Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sun, 19 Jul 2020 20:34:04 -0700 Subject: [PATCH] core: add Labels --- crates/bevy_core/src/label.rs | 90 +++++++++++++++++++++++++++++++++++ crates/bevy_core/src/lib.rs | 5 +- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 crates/bevy_core/src/label.rs diff --git a/crates/bevy_core/src/label.rs b/crates/bevy_core/src/label.rs new file mode 100644 index 0000000000..185ada37fd --- /dev/null +++ b/crates/bevy_core/src/label.rs @@ -0,0 +1,90 @@ +use bevy_ecs::prelude::*; +use bevy_property::Properties; +use std::{ + borrow::Cow, + collections::{HashMap, HashSet}, ops::{DerefMut, Deref}, fmt::Debug, +}; + +#[derive(Default, Properties)] +pub struct Labels { + labels: HashSet>, +} + +impl Debug for Labels { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut list = f.debug_list(); + for label in self.iter() { + list.entry(&label); + } + + list.finish() + } +} + +impl<'a, T, L: Into>> From for Labels where T: IntoIterator { + fn from(value: T) -> Self { + let mut labels = HashSet::new(); + for label in value { + labels.insert(label.into()); + } + Self { + labels, + } + } +} + +impl Labels { + pub fn contains>>(&self, label: T) -> bool { + self.labels.contains(&label.into()) + } + + pub fn insert>>(&mut self, label: T) { + self.labels.insert(label.into()); + } + + pub fn iter(&self) -> impl Iterator { + self.labels.iter().map(|label| label.deref()) + } +} + +#[derive(Default)] +pub struct EntityLabels { + label_entities: HashMap, Vec>, + entity_labels: HashMap>>, +} + +impl EntityLabels { + pub fn get(&self, label: &str) -> Option<&[Entity]> { + self.label_entities + .get(label) + .map(|entities| entities.as_slice()) + } +} + +pub fn entity_labels_system( + mut entity_labels: ResMut, + // TODO: use change tracking when add/remove events are added + // mut query: Query<(Entity, Changed)>, + mut query: Query<(Entity, &Labels)>, +) { + let entity_labels = entity_labels.deref_mut(); + for (entity, labels) in &mut query.iter() { + let current_labels = entity_labels + .entity_labels + .entry(entity) + .or_insert_with(|| HashSet::default()); + for removed_label in current_labels.difference(&labels.labels) { + if let Some(entities) = entity_labels.label_entities.get_mut(removed_label) { + entities.retain(|e| *e != entity); + } + } + + for added_label in labels.labels.difference(¤t_labels) { + if let Some(entities) = entity_labels.label_entities.get_mut(added_label) { + entities.push(entity); + } + } + + *current_labels = labels.labels.clone(); + } +} diff --git a/crates/bevy_core/src/lib.rs b/crates/bevy_core/src/lib.rs index 7ec27a0f10..4d14ebf2ed 100644 --- a/crates/bevy_core/src/lib.rs +++ b/crates/bevy_core/src/lib.rs @@ -1,13 +1,15 @@ mod bytes; mod float_ord; mod time; +mod label; pub use bytes::*; pub use float_ord::*; pub use time::*; +pub use label::*; pub mod prelude { - pub use crate::{Time, Timer}; + pub use crate::{Time, Timer, Labels, EntityLabels}; } use bevy_app::prelude::*; @@ -21,6 +23,7 @@ pub struct CorePlugin; impl AppPlugin for CorePlugin { fn build(&self, app: &mut AppBuilder) { app.init_resource::