Skip to content
Snippets Groups Projects
window_context_provider.rs 2.69 KiB
Newer Older
Louis's avatar
Louis committed
use bevy::{prelude::*, utils::HashMap};

use crate::{
    children::KChildren, context::WidgetName, prelude::KayakWidgetContext, widget::Widget,
};

#[derive(Component, Default, Debug, Clone, PartialEq, Eq)]
pub struct WindowContext {
    order: Vec<Entity>,
    z_indices: HashMap<Entity, usize>,
}

impl WindowContext {
    pub fn add(&mut self, entity: Entity, index: usize) {
        self.order.push(entity);
        self.z_indices.insert(entity, index);
    }

    pub fn shift_to_top(&mut self, entity: Entity) {
        if let Some(index) = self.order.iter().position(|e| *e == entity) {
            self.order.remove(index);
            self.order.push(entity);
        }

        self.z_indices.clear();
        for (index, entity) in self.order.iter().enumerate() {
            self.z_indices.insert(*entity, index);
        }
    }

    pub fn get(&self, entity: Entity) -> usize {
        *self.z_indices.get(&entity).unwrap()
    }

    pub fn get_or_add(&mut self, entity: Entity) -> usize {
        if self.order.iter().any(|e| *e == entity) {
            self.get(entity)
        } else {
            self.add(entity, 0);
            self.shift_to_top(entity);
            self.get(entity)
        }
    }
}

#[derive(Component, Default, Debug, Clone, PartialEq, Eq)]
pub struct WindowContextProvider;

impl Widget for WindowContextProvider {}

#[derive(Bundle, Debug, Clone, PartialEq, Eq)]
pub struct WindowContextProviderBundle {
    pub context_provider: WindowContextProvider,
    pub children: KChildren,
    pub widget_name: WidgetName,
}

impl Default for WindowContextProviderBundle {
    fn default() -> Self {
        Self {
            context_provider: Default::default(),
            children: Default::default(),
            widget_name: WindowContextProvider.get_name(),
        }
    }
}

pub fn window_context_render(
    In(window_context_entity): In<Entity>,
    widget_context: Res<KayakWidgetContext>,
    mut commands: Commands,
    children_query: Query<&KChildren>,
) -> bool {
    if let Ok(children) = children_query.get(window_context_entity) {
        let context_entity = if let Some(context_entity) =
            widget_context.get_context_entity::<WindowContext>(window_context_entity)
        {
            context_entity
        } else {
            commands
                .spawn(WindowContext::default())
                .set_parent(window_context_entity)
                .id()
        };
        widget_context
            .set_context_entity::<WindowContext>(Some(window_context_entity), context_entity);
        children.process(&widget_context, &mut commands, Some(window_context_entity));
    }

    true
}