use alloc::string::String;
use crate::components::{DebugHud, StatHud, TextLabel};
use crate::ecs::PipelineContext;
use crate::ecs::asset_id::AssetId;
use crate::ecs::{ComponentSlot, FontHandle};
use crate::result::CnResult;
use super::Minter;
type Slot<H> = fn(&mut H) -> &mut Option<AssetId>;
const DEBUG_SLOTS: [Slot<DebugHud>; 4] = [
|h| &mut h.passes_label,
|h| &mut h.mouse_label,
|h| &mut h.camera_label,
|h| &mut h.sys_label,
];
const STAT_SLOTS: [Slot<StatHud>; 5] = [
|h| &mut h.fps_label,
|h| &mut h.vram_label,
|h| &mut h.ram_label,
|h| &mut h.ev_label,
|h| &mut h.edr_label,
];
pub(super) fn inject_debug_hud(
ctx: &mut PipelineContext,
minter: &mut Minter,
) -> Result<(), CnResult> {
complete(ctx, minter, &DEBUG_SLOTS, true)
}
pub(super) fn complete_stat_hud(
ctx: &mut PipelineContext,
minter: &mut Minter,
) -> Result<(), CnResult> {
complete(ctx, minter, &STAT_SLOTS, false)
}
fn complete<H>(
ctx: &mut PipelineContext,
minter: &mut Minter,
slots: &[Slot<H>],
synthesize: bool,
) -> Result<(), CnResult>
where
H: ComponentSlot + Clone + Default,
{
let declared = ctx.query::<H>().next().is_some();
if !declared && !synthesize {
return Ok(());
}
let mut hud = ctx.query::<H>().next().cloned().unwrap_or_default();
let unset: alloc::vec::Vec<usize> = (0..slots.len())
.filter(|&i| slots[i](&mut hud).is_none())
.collect();
if !unset.is_empty() {
let font = minter.hud_font(ctx)?;
for i in unset {
let id = minter.id();
*slots[i](&mut hud) = Some(id);
ctx.push(chip(id, font));
}
}
match ctx.query_mut::<H>().next() {
Some(existing) => *existing = hud,
None => ctx.push(hud),
}
Ok(())
}
fn chip(id: AssetId, font: FontHandle) -> TextLabel {
TextLabel {
asset_id: id,
font: Some(font),
content: String::new(),
scale: 0.7,
color: [1.0, 1.0, 1.0],
background: [0.0, 0.18, 0.32, 0.85],
padding: 5.0,
..Default::default()
}
}