Skip to content
Snippets Groups Projects
widget_state.rs 2.03 KiB
Newer Older
Louis's avatar
Louis committed
use bevy::prelude::{BuildChildren, Commands, Component, Entity, Resource};
use dashmap::DashMap;
use std::sync::Arc;

/// Stores mappings between widget entities and their corresponding state entities.
#[derive(Resource, Default, Debug, Clone)]
pub struct WidgetState {
    // Widget entity to state entity
    mapping: Arc<DashMap<Entity, Entity>>,
    // State entity to widget entity
    reverse_mapping: Arc<DashMap<Entity, Entity>>,
}

impl WidgetState {
    /// Attempts to create a state entity or return the existing entity.
    pub fn add<State: Component + PartialEq + Clone>(
        &self,
        commands: &mut Commands,
        widget_entity: Entity,
        initial_state: State,
    ) -> Entity {
        if self.mapping.contains_key(&widget_entity) {
            *self.mapping.get(&widget_entity).unwrap()
        } else {
            let mut state_entity = None;
            commands
                .entity(widget_entity)
                .with_children(|child_builder| {
                    state_entity = Some(child_builder.spawn(initial_state).id());
                    self.mapping.insert(widget_entity, state_entity.unwrap());
                    self.reverse_mapping
                        .insert(state_entity.unwrap(), widget_entity);
                });
            state_entity.expect("State entity did not spawn!")
        }
    }

    /// Attempts to get a state entity
    pub fn get(&self, widget_entity: Entity) -> Option<Entity> {
        self.mapping.get(&widget_entity).map(|entry| *entry.value())
    }

    pub fn get_widget_entity(&self, state_entity: Entity) -> Option<Entity> {
        self.reverse_mapping
            .get(&state_entity)
            .map(|entry| *entry.value())
    }

    pub fn remove(&self, widget_entity: Entity) -> Option<Entity> {
        let state_entity = self.mapping.remove(&widget_entity).map(|(_, v)| v);
        if let Some(state_entity) = state_entity {
            self.reverse_mapping.remove(&state_entity);
        }
        state_entity
    }
}