oxygengine-composite-renderer 0.30.0

Composite renderer module for Oxygengine
Documentation
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()))
    }
}