oxygengine_composite_renderer/system/
surface_cache.rs1use 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}