oxygengine_composite_renderer/
resource.rs

1use crate::math::{Mat2d, Rect, Vec2};
2use core::ecs::Entity;
3use std::collections::HashMap;
4
5#[derive(Debug, Default)]
6pub struct CompositeTransformCache {
7    matrix: HashMap<Entity, Mat2d>,
8    matrix_inverse: HashMap<Entity, Mat2d>,
9}
10
11impl CompositeTransformCache {
12    pub fn matrix(&self, entity: Entity) -> Option<Mat2d> {
13        self.matrix.get(&entity).copied()
14    }
15
16    pub fn inverse_matrix(&self, entity: Entity) -> Option<Mat2d> {
17        self.matrix_inverse.get(&entity).copied()
18    }
19
20    pub fn insert(&mut self, entity: Entity, matrix: Mat2d) {
21        self.matrix.insert(entity, matrix);
22        self.matrix_inverse
23            .insert(entity, (!matrix).unwrap_or_default());
24    }
25
26    pub fn remove(&mut self, entity: Entity) {
27        self.matrix.remove(&entity);
28        self.matrix_inverse.remove(&entity);
29    }
30
31    pub fn clear(&mut self) {
32        self.matrix.clear();
33        self.matrix_inverse.clear();
34    }
35}
36
37#[derive(Debug, Default)]
38pub struct CompositeCameraCache {
39    pub(crate) last_view_size: Vec2,
40    pub(crate) world_transforms: HashMap<Entity, Mat2d>,
41    pub(crate) world_inverse_transforms: HashMap<Entity, Mat2d>,
42}
43
44impl CompositeCameraCache {
45    pub fn last_view_size(&self) -> Vec2 {
46        self.last_view_size
47    }
48
49    pub fn screen_to_world_space(&self, entity: Entity, point: Vec2) -> Option<Vec2> {
50        self.world_inverse_transforms
51            .get(&entity)
52            .map(|m| *m * point)
53    }
54
55    pub fn world_to_screen_space(&self, entity: Entity, point: Vec2) -> Option<Vec2> {
56        self.world_transforms.get(&entity).map(|m| *m * point)
57    }
58
59    pub fn world_transform(&self, entity: Entity) -> Option<Mat2d> {
60        self.world_transforms.get(&entity).cloned()
61    }
62
63    pub fn world_inverse_transform(&self, entity: Entity) -> Option<Mat2d> {
64        self.world_inverse_transforms.get(&entity).cloned()
65    }
66
67    pub fn world_both_transforms(&self, entity: Entity) -> Option<(Mat2d, Mat2d)> {
68        if let Some(t) = self.world_transforms.get(&entity) {
69            if let Some(i) = self.world_inverse_transforms.get(&entity) {
70                return Some((*t, *i));
71            }
72        }
73        None
74    }
75
76    pub fn calculate_view_box(&self, entity: Entity) -> Option<Rect> {
77        let m = self.world_inverse_transforms.get(&entity)?;
78        let p1 = *m * Vec2::new(0.0, 0.0);
79        let p2 = *m * Vec2::new(self.last_view_size.x, 0.0);
80        let p3 = *m * self.last_view_size;
81        let p4 = *m * Vec2::new(0.0, self.last_view_size.y);
82        Rect::bounding(&[p1, p2, p3, p4])
83    }
84
85    pub fn calculate_world_size(&self, entity: Entity) -> Option<Vec2> {
86        let m = self.world_inverse_transforms.get(&entity)?;
87        let p1 = *m * Vec2::new(0.0, 0.0);
88        let p2 = *m * Vec2::new(self.last_view_size.x, 0.0);
89        let p3 = *m * Vec2::new(0.0, self.last_view_size.y);
90        Some(Vec2::new((p2 - p1).magnitude(), (p3 - p1).magnitude()))
91    }
92}