oxygengine_composite_renderer/system/
surface_cache.rs

1use crate::{
2    component::{CompositeRenderable, CompositeSurfaceCache},
3    composite_renderer::{Command, CompositeRenderer, Image},
4};
5use core::ecs::{life_cycle::EntityChanges, Comp, Entity, Universe, WorldRef};
6use std::collections::HashMap;
7
8#[derive(Debug, Default)]
9pub struct CompositeSurfaceCacheSystemCache {
10    cached_surfaces: HashMap<Entity, String>,
11}
12
13pub type CompositeSurfaceCacheSystemResources<'a, CR> = (
14    WorldRef,
15    &'a mut CR,
16    &'a EntityChanges,
17    &'a mut CompositeSurfaceCacheSystemCache,
18    Comp<&'a mut CompositeSurfaceCache>,
19    Comp<&'a mut CompositeRenderable>,
20);
21
22pub fn composite_surface_cache_system<CR>(universe: &mut Universe)
23where
24    CR: CompositeRenderer + 'static,
25{
26    let (world, mut renderer, changes, mut cache, ..) =
27        universe.query_resources::<CompositeSurfaceCacheSystemResources<CR>>();
28
29    for entity in changes.despawned() {
30        if let Some(name) = cache.cached_surfaces.remove(&entity) {
31            renderer.destroy_surface(&name);
32        }
33    }
34
35    for (entity, (surface, renderable)) in world
36        .query::<(&mut CompositeSurfaceCache, &mut CompositeRenderable)>()
37        .iter()
38    {
39        if surface.dirty {
40            surface.dirty = false;
41            if !renderer.has_surface(surface.name()) {
42                renderer.create_surface(surface.name(), surface.width(), surface.height());
43                cache
44                    .cached_surfaces
45                    .insert(entity, surface.name().to_owned());
46            } else if let Some((width, height)) = renderer.get_surface_size(surface.name()) {
47                if width != surface.width() || height != surface.height() {
48                    renderer.destroy_surface(surface.name());
49                    renderer.create_surface(surface.name(), surface.width(), surface.height());
50                    cache
51                        .cached_surfaces
52                        .insert(entity, surface.name().to_owned());
53                }
54            }
55            let commands = vec![
56                Command::Store,
57                Command::Draw(renderable.0.clone()),
58                Command::Restore,
59            ];
60            if renderer.update_surface(surface.name(), commands).is_ok() {
61                renderable.0 = Image {
62                    image: surface.name().to_owned().into(),
63                    source: None,
64                    destination: None,
65                    alignment: 0.0.into(),
66                }
67                .into();
68            }
69        }
70    }
71}