vox_engine 0.3.0

voxel game engine
use dear_imgui_reflect::ImGuiReflect;
use getset::Getters;
use std::collections::HashMap;

use rapier3d::glamx::{Vec3, Vec4};

use crate::common::LocalLight;

use super::{AnimationType, light::Light};

#[derive(ImGuiReflect, Getters)]
pub struct LightManager {
    lights: HashMap<String, Light>,
    #[getset(get = "pub with_prefix")]
    size: usize,
}

impl LightManager {
    pub fn new(size: usize) -> Self {
        let lights: HashMap<String, Light> = HashMap::with_capacity(size);

        Self { lights, size }
    }
}

impl LightManager {
    pub fn add_light(
        &mut self,
        position: Vec3,
        color_intensity: Vec4,
        lifetime: Option<f64>,
        position_animation: Option<AnimationType>,
        color_animation: Option<AnimationType>,
        world_extents: [u32; 3],
    ) {
        let light_id = (world_extents[0]
            * ((position.z as u32 * world_extents[1]) + position.x as u32))
            + position.y as u32;

        let light = Light::new(
            position,
            color_intensity,
            lifetime,
            position_animation,
            color_animation,
        );

        self.lights.entry(format!("{light_id}")).or_insert(light);
    }

    pub fn get_lights_as_array(&self) -> Vec<LocalLight> {
        self.lights
            .clone()
            .into_values()
            .collect::<Vec<Light>>()
            .into_iter()
            .map(|light| LocalLight {
                pos_radius: light.get_position().extend(0.0).to_array(),
                color_intensity: light.get_color_intensity().to_array(),
            })
            .collect()
    }

    pub fn get_amount_of_active_lights(&self) -> u32 {
        self.lights
            .clone()
            .into_values()
            .collect::<Vec<Light>>()
            .into_iter()
            .filter(|light| {
                let lifetime = light.get_lifetime();
                match lifetime {
                    None => {
                        return true;
                    }
                    Some(lifetime) => {
                        if lifetime > 0.0 {
                            return true;
                        };
                        return false;
                    }
                }
            })
            .count() as u32
    }

    pub fn update_lights(&mut self) {
        self.lights.retain(|_, light| {
            let lifetime = light.get_lifetime();
            match lifetime {
                None => {
                    light.apply_position_animation();
                    light.apply_color_animation();

                    return true;
                }
                Some(lifetime) => {
                    if lifetime <= 0.0 {
                        return false;
                    };

                    light.apply_position_animation();
                    light.apply_color_animation();
                    light.decay();

                    return true;
                }
            }
        });
    }
}