use crate::element::{Element, ElementId, ElementState};
use bevy::asset::Asset;
use bevy::prelude::{Commands, Entity, GlobalTransform, Transform, TypePath, Visibility, World};
use bevy::ui::Node;
use rustc_hash::FxHashMap;
#[derive(Debug, Asset, TypePath)]
pub struct Page {
root: Node,
entity: Option<Entity>,
registry: FxHashMap<ElementId, Entity>,
elements: Vec<Element>,
active: bool,
}
impl Page {
#[inline(always)]
pub fn new(root: Node, elements: Vec<Element>) -> Self {
Self {
root,
entity: None,
registry: FxHashMap::with_capacity_and_hasher(elements.len(), Default::default()),
elements,
active: false,
}
}
pub fn spawn(&mut self, world: &mut World) {
let root_entity = world
.spawn((
self.root.clone(),
Transform::default(),
GlobalTransform::default(),
Visibility::Hidden,
))
.id();
for element in &self.elements {
element.spawn(world, Some(root_entity), &mut self.registry);
}
self.entity = Some(root_entity);
}
#[inline(always)]
pub fn get(&self, id: impl Into<ElementId>) -> Entity {
self.try_get(id).expect("Element not found")
}
#[inline(always)]
pub fn try_get(&self, id: impl Into<ElementId>) -> Option<Entity> {
self.registry.get(&id.into()).copied()
}
#[inline(always)]
pub fn entity(&self) -> Option<Entity> {
self.entity
}
pub fn is_active(&self) -> bool {
self.active
}
pub fn set_active(&mut self, commands: &mut Commands, active: bool) {
let mut entity = commands.entity(self.entity.expect("Page not spawned yet"));
if active {
entity.insert((Visibility::Visible, ElementState::Active));
} else {
entity.insert((Visibility::Hidden, ElementState::Inactive));
}
self.active = active;
}
}