nightshade 0.8.0

A cross-platform data-oriented game engine.
Documentation
use crate::prelude::*;

use super::modal::Modals;

pub struct WidgetEntry<W> {
    pub name: String,
    pub create: fn() -> W,
}

pub struct WidgetContext<'a, C = (), M = ()> {
    pub(crate) world: &'a mut World,
    pub viewport_textures: &'a [egui::TextureId],
    pub current_tile_id: egui_tiles::TileId,
    pub selected_viewport_tile: &'a mut Option<egui_tiles::TileId>,
    pub modals: &'a mut Modals,
    pub app: &'a mut C,
    pub window_index: Option<usize>,
    pub is_active_window: bool,
    pub cached_cameras: &'a [Entity],
    pub(crate) messages: &'a mut Vec<M>,
    pub(crate) incoming_messages: &'a mut std::collections::HashMap<egui_tiles::TileId, Vec<M>>,
}

impl<C, M> WidgetContext<'_, C, M> {
    pub fn world(&self) -> &World {
        self.world
    }

    pub fn world_mut(&mut self) -> &mut World {
        self.world
    }

    pub fn world_and_app(&mut self) -> (&mut World, &mut C) {
        (self.world, self.app)
    }

    pub fn world_app_modals(&mut self) -> (&mut World, &mut C, &mut Modals) {
        (self.world, self.app, self.modals)
    }

    pub fn send(&mut self, message: M) {
        self.messages.push(message);
    }

    pub fn receive(&mut self) -> Vec<M> {
        self.incoming_messages
            .remove(&self.current_tile_id)
            .unwrap_or_default()
    }

    pub fn has_incoming(&self) -> bool {
        self.incoming_messages
            .get(&self.current_tile_id)
            .is_some_and(|messages| !messages.is_empty())
    }
}

pub trait Widget<C = (), M = ()>:
    Clone + serde::Serialize + serde::de::DeserializeOwned + 'static
{
    fn title(&self) -> String;
    fn ui(&mut self, ui: &mut egui::Ui, context: &mut WidgetContext<C, M>);

    fn on_add(&mut self, _context: &mut WidgetContext<C, M>) {}
    fn on_remove(&mut self, _context: &mut WidgetContext<C, M>) {}

    fn closable(&self) -> bool {
        true
    }

    fn required_camera(&self, _cached_cameras: &[Entity]) -> Option<Entity> {
        None
    }

    fn catalog() -> Vec<WidgetEntry<Self>>
    where
        Self: Sized;
}

#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Pane<W> {
    pub widget: W,
}

impl<W> Pane<W> {
    pub fn new(widget: W) -> Self {
        Self { widget }
    }
}