use crate::mosaic::behavior::{TileBehavior, TileBehaviorWithWorld};
use crate::mosaic::widget::{Pane, Widget, WidgetContext};
use nightshade::prelude::*;
use super::Mosaic;
impl<W: Widget<C, M>, C, M> Mosaic<W, C, M> {
pub fn show_inside(&mut self, world: &mut World, ui: &mut egui::Ui, app: &mut C) {
self.prepare(world);
let mut tree = self.tile_tree.take();
Self::render_tree(
&mut tree,
&mut self.behavior,
world,
app,
&mut self.pending_messages,
ui,
);
self.process_pending_removals(world, app);
self.finish(tree);
}
fn render_tree(
tree: &mut Option<egui_tiles::Tree<Pane<W>>>,
behavior: &mut TileBehavior<W, C, M>,
world: &mut World,
app: &mut C,
pending: &mut Vec<M>,
ui: &mut egui::Ui,
) {
if let Some(tree) = tree {
{
let mut behavior_with_world = TileBehaviorWithWorld {
behavior: &mut *behavior,
world: &mut *world,
app: &mut *app,
messages: &mut *pending,
};
tree.ui(&mut behavior_with_world, ui);
}
Self::process_pending_add(behavior, tree, app, world, pending);
}
}
pub(super) fn prepare(&mut self, world: &mut World) {
self.behavior.viewport_rects.clear();
self.behavior.viewport_textures.clear();
let source_textures = self
.viewport_texture_overrides
.as_ref()
.unwrap_or(&world.resources.user_interface.viewport_textures);
self.behavior
.viewport_textures
.extend_from_slice(source_textures);
self.behavior.config = self.config.clone();
self.behavior.is_active_window = self.is_active_window;
self.behavior.cached_cameras.clear();
self.behavior
.cached_cameras
.extend(world.core.query_entities(CAMERA));
self.behavior.cached_cameras.sort_by_key(|entity| entity.id);
if let Some(tree) = &self.tile_tree {
for (_tile_id, tile) in tree.tiles.iter() {
if let egui_tiles::Tile::Pane(pane) = tile
&& let Some(camera_entity) =
pane.widget.required_camera(&self.behavior.cached_cameras)
&& !world
.resources
.user_interface
.required_cameras
.contains(&camera_entity)
{
world
.resources
.user_interface
.required_cameras
.push(camera_entity);
world
.resources
.user_interface
.required_camera_sizes
.push((0, 0));
}
}
}
}
pub(super) fn finish(&mut self, tree: Option<egui_tiles::Tree<Pane<W>>>) {
self.tile_tree = tree;
self.incoming_messages.clear();
if self.behavior.layout_modified {
self.layout_modified = true;
self.behavior.layout_modified = false;
}
}
fn process_pending_add(
behavior: &mut TileBehavior<W, C, M>,
tree: &mut egui_tiles::Tree<Pane<W>>,
app: &mut C,
world: &mut World,
messages: &mut Vec<M>,
) {
if let Some((tile_id, catalog_index)) = behavior.pending_add_widget.take() {
let catalog = W::catalog();
if let Some(entry) = catalog.get(catalog_index) {
let mut new_widget = (entry.create)();
let new_pane = Pane::new(new_widget.clone());
let new_tile_id = tree.tiles.insert_pane(new_pane);
Self::add_to_container(&mut tree.tiles, tile_id, new_tile_id);
let mut context = WidgetContext {
world,
selected_viewport_tile: &mut behavior.selected_viewport_tile,
viewport_textures: &behavior.viewport_textures,
current_tile_id: new_tile_id,
app,
cached_cameras: &behavior.cached_cameras,
messages,
};
new_widget.on_add(&mut context);
if let Some(egui_tiles::Tile::Pane(pane)) = tree.tiles.get_mut(new_tile_id) {
pane.widget = new_widget;
}
}
}
}
fn process_pending_removals(&mut self, world: &mut World, app: &mut C) {
let removals = std::mem::take(&mut self.behavior.pending_removals);
for (tile_id, mut widget) in removals {
let mut context = WidgetContext {
world: &mut *world,
selected_viewport_tile: &mut self.behavior.selected_viewport_tile,
viewport_textures: &self.behavior.viewport_textures,
current_tile_id: tile_id,
app: &mut *app,
cached_cameras: &self.behavior.cached_cameras,
messages: &mut self.pending_messages,
};
widget.on_remove(&mut context);
}
}
}