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