oxygengine-composite-renderer 0.30.0

Composite renderer module for Oxygengine
Documentation
use crate::{
    component::{CompositeRenderable, CompositeSurfaceCache},
    composite_renderer::{Command, CompositeRenderer, Image},
};
use core::ecs::{life_cycle::EntityChanges, Comp, Entity, Universe, WorldRef};
use std::collections::HashMap;

#[derive(Debug, Default)]
pub struct CompositeSurfaceCacheSystemCache {
    cached_surfaces: HashMap<Entity, String>,
}

pub type CompositeSurfaceCacheSystemResources<'a, CR> = (
    WorldRef,
    &'a mut CR,
    &'a EntityChanges,
    &'a mut CompositeSurfaceCacheSystemCache,
    Comp<&'a mut CompositeSurfaceCache>,
    Comp<&'a mut CompositeRenderable>,
);

pub fn composite_surface_cache_system<CR>(universe: &mut Universe)
where
    CR: CompositeRenderer + 'static,
{
    let (world, mut renderer, changes, mut cache, ..) =
        universe.query_resources::<CompositeSurfaceCacheSystemResources<CR>>();

    for entity in changes.despawned() {
        if let Some(name) = cache.cached_surfaces.remove(&entity) {
            renderer.destroy_surface(&name);
        }
    }

    for (entity, (surface, renderable)) in world
        .query::<(&mut CompositeSurfaceCache, &mut CompositeRenderable)>()
        .iter()
    {
        if surface.dirty {
            surface.dirty = false;
            if !renderer.has_surface(surface.name()) {
                renderer.create_surface(surface.name(), surface.width(), surface.height());
                cache
                    .cached_surfaces
                    .insert(entity, surface.name().to_owned());
            } else if let Some((width, height)) = renderer.get_surface_size(surface.name()) {
                if width != surface.width() || height != surface.height() {
                    renderer.destroy_surface(surface.name());
                    renderer.create_surface(surface.name(), surface.width(), surface.height());
                    cache
                        .cached_surfaces
                        .insert(entity, surface.name().to_owned());
                }
            }
            let commands = vec![
                Command::Store,
                Command::Draw(renderable.0.clone()),
                Command::Restore,
            ];
            if renderer.update_surface(surface.name(), commands).is_ok() {
                renderable.0 = Image {
                    image: surface.name().to_owned().into(),
                    source: None,
                    destination: None,
                    alignment: 0.0.into(),
                }
                .into();
            }
        }
    }
}