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