core: add Labels
This commit is contained in:
		
							parent
							
								
									9a236f4923
								
							
						
					
					
						commit
						d8b3d078b4
					
				
							
								
								
									
										90
									
								
								crates/bevy_core/src/label.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								crates/bevy_core/src/label.rs
									
									
									
									
									
										Normal file
									
								
							@ -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<Cow<'static, str>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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<Cow<'static, str>>> From<T> for Labels where T: IntoIterator<Item=L> {
 | 
				
			||||||
 | 
					    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<T: Into<Cow<'static, str>>>(&self, label: T) -> bool {
 | 
				
			||||||
 | 
					        self.labels.contains(&label.into())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn insert<T: Into<Cow<'static, str>>>(&mut self, label: T) {
 | 
				
			||||||
 | 
					        self.labels.insert(label.into());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn iter(&self) -> impl Iterator<Item = &str> {
 | 
				
			||||||
 | 
					        self.labels.iter().map(|label| label.deref())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Default)]
 | 
				
			||||||
 | 
					pub struct EntityLabels {
 | 
				
			||||||
 | 
					    label_entities: HashMap<Cow<'static, str>, Vec<Entity>>,
 | 
				
			||||||
 | 
					    entity_labels: HashMap<Entity, HashSet<Cow<'static, str>>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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<EntityLabels>,
 | 
				
			||||||
 | 
					    // TODO: use change tracking when add/remove events are added
 | 
				
			||||||
 | 
					    // mut query: Query<(Entity, Changed<Labels>)>,
 | 
				
			||||||
 | 
					    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();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,13 +1,15 @@
 | 
				
			|||||||
mod bytes;
 | 
					mod bytes;
 | 
				
			||||||
mod float_ord;
 | 
					mod float_ord;
 | 
				
			||||||
mod time;
 | 
					mod time;
 | 
				
			||||||
 | 
					mod label;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use bytes::*;
 | 
					pub use bytes::*;
 | 
				
			||||||
pub use float_ord::*;
 | 
					pub use float_ord::*;
 | 
				
			||||||
pub use time::*;
 | 
					pub use time::*;
 | 
				
			||||||
 | 
					pub use label::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod prelude {
 | 
					pub mod prelude {
 | 
				
			||||||
    pub use crate::{Time, Timer};
 | 
					    pub use crate::{Time, Timer, Labels, EntityLabels};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use bevy_app::prelude::*;
 | 
					use bevy_app::prelude::*;
 | 
				
			||||||
@ -21,6 +23,7 @@ pub struct CorePlugin;
 | 
				
			|||||||
impl AppPlugin for CorePlugin {
 | 
					impl AppPlugin for CorePlugin {
 | 
				
			||||||
    fn build(&self, app: &mut AppBuilder) {
 | 
					    fn build(&self, app: &mut AppBuilder) {
 | 
				
			||||||
        app.init_resource::<Time>()
 | 
					        app.init_resource::<Time>()
 | 
				
			||||||
 | 
					            .init_resource::<EntityLabels>()
 | 
				
			||||||
            .register_component::<Timer>()
 | 
					            .register_component::<Timer>()
 | 
				
			||||||
            .register_property_type::<Vec2>()
 | 
					            .register_property_type::<Vec2>()
 | 
				
			||||||
            .register_property_type::<Vec3>()
 | 
					            .register_property_type::<Vec3>()
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user