#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct LightCountOverlayConfig {
pub enabled: bool,
pub tile_size_px: u32,
pub max_lights: u32,
pub color_zero: [f32; 4],
pub color_max: [f32; 4],
pub show_numbers: bool,
pub opacity: f32,
}
impl Default for LightCountOverlayConfig {
fn default() -> Self {
Self {
enabled: false,
tile_size_px: 16,
max_lights: 32,
color_zero: [0.0, 0.0, 0.5, 0.5],
color_max: [1.0, 0.0, 0.0, 0.8],
show_numbers: true,
opacity: 0.6,
}
}
}
#[allow(dead_code)]
pub fn new_light_count_overlay_config() -> LightCountOverlayConfig {
LightCountOverlayConfig::default()
}
#[allow(dead_code)]
pub fn light_count_to_color(count: u32, cfg: &LightCountOverlayConfig) -> [f32; 4] {
let t = (count as f32 / cfg.max_lights as f32).clamp(0.0, 1.0);
let inv = 1.0 - t;
let r = cfg.color_zero[0] * inv + cfg.color_max[0] * t;
let g = cfg.color_zero[1] * inv + cfg.color_max[1] * t;
let b = cfg.color_zero[2] * inv + cfg.color_max[2] * t;
let a = cfg.color_zero[3] * inv + cfg.color_max[3] * t;
[r, g, b, a * cfg.opacity]
}
#[allow(dead_code)]
pub fn lco_enable(cfg: &mut LightCountOverlayConfig) {
cfg.enabled = true;
}
#[allow(dead_code)]
pub fn lco_disable(cfg: &mut LightCountOverlayConfig) {
cfg.enabled = false;
}
#[allow(dead_code)]
pub fn lco_set_tile_size(cfg: &mut LightCountOverlayConfig, size: u32) {
cfg.tile_size_px = size.clamp(4, 128);
}
#[allow(dead_code)]
pub fn lco_set_max_lights(cfg: &mut LightCountOverlayConfig, max: u32) {
cfg.max_lights = max.max(1);
}
#[allow(dead_code)]
pub fn lco_set_opacity(cfg: &mut LightCountOverlayConfig, opacity: f32) {
cfg.opacity = opacity.clamp(0.0, 1.0);
}
#[allow(dead_code)]
pub fn lco_tile_grid(width: u32, height: u32, cfg: &LightCountOverlayConfig) -> (u32, u32) {
let ts = cfg.tile_size_px.max(1);
(width.div_ceil(ts), height.div_ceil(ts))
}
#[allow(dead_code)]
pub fn lco_average_lights(tile_counts: &[u32]) -> f32 {
if tile_counts.is_empty() {
return 0.0;
}
let sum: u64 = tile_counts.iter().map(|&c| c as u64).sum();
sum as f32 / tile_counts.len() as f32
}
#[allow(dead_code)]
pub fn light_count_overlay_to_json(cfg: &LightCountOverlayConfig) -> String {
format!(
r#"{{"enabled":{},"tile_size_px":{},"max_lights":{},"opacity":{:.4}}}"#,
cfg.enabled, cfg.tile_size_px, cfg.max_lights, cfg.opacity
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default() {
let c = LightCountOverlayConfig::default();
assert!(!c.enabled);
assert_eq!(c.tile_size_px, 16);
}
#[test]
fn test_color_zero() {
let c = LightCountOverlayConfig::default();
let col = light_count_to_color(0, &c);
assert!((col[2] - c.color_zero[2]).abs() < 1e-4);
}
#[test]
fn test_color_max_red() {
let c = LightCountOverlayConfig::default();
let col = light_count_to_color(c.max_lights, &c);
assert!(col[0] > col[2]);
}
#[test]
fn test_enable_disable() {
let mut c = LightCountOverlayConfig::default();
lco_enable(&mut c);
assert!(c.enabled);
lco_disable(&mut c);
assert!(!c.enabled);
}
#[test]
fn test_set_tile_size_clamp() {
let mut c = LightCountOverlayConfig::default();
lco_set_tile_size(&mut c, 0);
assert!(c.tile_size_px >= 4);
}
#[test]
fn test_set_max_lights_min() {
let mut c = LightCountOverlayConfig::default();
lco_set_max_lights(&mut c, 0);
assert_eq!(c.max_lights, 1);
}
#[test]
fn test_tile_grid() {
let c = LightCountOverlayConfig::default();
let (tx, ty) = lco_tile_grid(1920, 1080, &c);
assert_eq!(tx, 120);
assert_eq!(ty, 68);
}
#[test]
fn test_average_lights() {
let tiles = [2u32, 4, 6];
let avg = lco_average_lights(&tiles);
assert!((avg - 4.0).abs() < 1e-5);
}
#[test]
fn test_average_lights_empty() {
assert!(lco_average_lights(&[]).abs() < 1e-6);
}
#[test]
fn test_to_json() {
let j = light_count_overlay_to_json(&LightCountOverlayConfig::default());
assert!(j.contains("tile_size_px"));
assert!(j.contains("max_lights"));
}
}