use crate::{
cell::CellFormat,
color::Color,
engine::Engine,
fps_counter::get_fps,
frame::DrawCall,
layer::LayerIndex,
rich_text::{Attributes, RichText},
};
#[rustfmt::skip]
pub(crate) static BLOCKTAD_CHAR_LUT: [char; 256] = [
' ', '๐บจ', '๐บซ', '๐ฎ', '๐ด', 'โ', '๐ด', '๐ด', '๐ด', '๐ด', 'โ', '๐ด
', '๐ด', '๐ด', '๐ด', 'โ',
'๐ด', '๐ด', '๐ด', '๐ด', '๐ฏฆ', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด',
'๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ด', '๐ฏง', '๐ด ', '๐ดก', '๐ดข', '๐ดฃ', '๐ดค', '๐ดฅ', '๐ดฆ',
'๐ดง', '๐ดจ', '๐ดฉ', '๐ดช', '๐ดซ', '๐ดฌ', '๐ดญ', '๐ดฎ', '๐ดฏ', '๐ดฐ', '๐ดฑ', '๐ดฒ', '๐ดณ', '๐ดด', '๐ดต', '๐ฎ
',
'๐บฃ', '๐ดถ', '๐ดท', '๐ดธ', '๐ดน', '๐ดบ', '๐ดป', '๐ดผ', '๐ดฝ', '๐ดพ', '๐ดฟ', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต',
'โ', '๐ต
', '๐ต', '๐ต', '๐ต', 'โ', '๐ต', '๐ต', '๐ต', '๐ต', 'โ', '๐ต', '๐ต', '๐ต', '๐ต', 'โ',
'๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต', '๐ต ',
'๐ตก', '๐ตข', '๐ตฃ', '๐ตค', '๐ตฅ', '๐ตฆ', '๐ตง', '๐ตจ', '๐ตฉ', '๐ตช', '๐ตซ', '๐ตฌ', '๐ตญ', '๐ตฎ', '๐ตฏ', '๐ตฐ',
'๐บ ', '๐ตฑ', '๐ตฒ', '๐ตณ', '๐ตด', '๐ตต', '๐ตถ', '๐ตท', '๐ตธ', '๐ตน', '๐ตบ', '๐ตป', '๐ตผ', '๐ตฝ', '๐ตพ', '๐ตฟ',
'๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ
', '๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ',
'โ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', 'โ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', 'โ', '๐ถ', '๐ถ', '๐ถ', '๐ถ', 'โ',
'๐ถ', '๐ถ', '๐ถ', '๐ถ', '๐ถ ', '๐ถก', '๐ถข', '๐ถฃ', '๐ถค', '๐ถฅ', '๐ถฆ', '๐ถง', '๐ถจ', '๐ถฉ', '๐ถช', '๐ถซ',
'โ', '๐ถฌ', '๐ถญ', '๐ถฎ', '๐ถฏ', '๐ถฐ', '๐ถฑ', '๐ถฒ', '๐ถณ', '๐ถด', '๐ถต', '๐ถถ', '๐ถท', '๐ถธ', '๐ถน', '๐ถบ',
'๐ถป', '๐ถผ', '๐ถฝ', '๐ถพ', '๐ถฟ', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท
', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท',
'๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท', '๐ท',
'โ', '๐ท', '๐ท', '๐ท', '๐ท', 'โ', '๐ท', '๐ท ', '๐ทก', '๐ทข', 'โ', '๐ทฃ', 'โ', '๐ทค', '๐ทฅ', 'โ',
];
pub fn draw_text(
engine: &mut Engine,
layer_index: LayerIndex,
x: i16,
y: i16,
text: impl Into<RichText>,
) {
let layer = &mut engine.frame.layered_draw_queue[layer_index.0];
let rich_text: RichText = text.into();
layer.0.push(DrawCall { rich_text, x, y });
}
pub fn fill_screen(engine: &mut Engine, layer_index: LayerIndex, color: Color) {
let width: i16 = engine.frame.width as i16;
let height: i16 = engine.frame.height as i16;
draw_rect(engine, layer_index, 0, 0, width, height, color);
}
pub fn erase_rect(
engine: &mut Engine,
layer_index: LayerIndex,
x: i16,
y: i16,
width: i16,
height: i16,
) {
let row_text: String = " ".repeat(width as usize);
let row_rich_text = RichText::new(row_text)
.with_fg(Color::CLEAR)
.with_bg(Color::CLEAR)
.with_attributes(Attributes::NO_FG_COLOR | Attributes::NO_BG_COLOR);
for row in 0..height {
draw_text(engine, layer_index, x, y + row, row_rich_text.clone())
}
}
pub fn draw_rect(
engine: &mut Engine,
layer_index: LayerIndex,
x: i16,
y: i16,
width: i16,
height: i16,
color: Color,
) {
let row_text: String = " ".repeat(width as usize);
let row_rich_text: RichText = RichText::new(&row_text)
.with_fg(Color::CLEAR)
.with_bg(color)
.with_attributes(Attributes::NO_FG_COLOR);
for row in 0..height {
draw_text(engine, layer_index, x, y + row, row_rich_text.clone())
}
}
pub fn draw_octad(engine: &mut Engine, layer_index: LayerIndex, x: f32, y: f32, color: Color) {
let cell_x: i16 = x.floor() as i16;
let cell_y: i16 = y.floor() as i16;
let sub_x: u8 = ((x - cell_x as f32) * 2.0).clamp(0.0, 1.0) as u8;
let sub_y_float: f32 = (y - cell_y as f32) * 4.0;
let sub_y: usize = sub_y_float.floor().clamp(0.0, 3.0) as usize;
let offset: usize = match (sub_x, sub_y) {
(0, 0) => 0,
(0, 1) => 1,
(0, 2) => 2,
(0, 3) => 6,
(1, 0) => 3,
(1, 1) => 4,
(1, 2) => 5,
(1, 3) => 7,
_ => panic!("Octad sub-position ({sub_x}, {sub_y}) falls out of range."),
};
let braille_char: char = std::char::from_u32(0x2800 + (1 << offset)).unwrap();
let rich_text: RichText = RichText::new(braille_char.to_string())
.with_fg(color)
.with_cell_format(CellFormat::Octad);
draw_text(engine, layer_index, cell_x, cell_y, rich_text);
}
pub fn draw_blocktad(engine: &mut Engine, layer_index: LayerIndex, x: f32, y: f32, color: Color) {
let cell_x: i16 = x.floor() as i16;
let cell_y: i16 = y.floor() as i16;
let sub_x: usize = (((x - cell_x as f32) * 2.0).floor().clamp(0.0, 1.0)) as usize;
let sub_y: usize = (((y - cell_y as f32) * 4.0).floor().clamp(0.0, 3.0)) as usize;
let offset: usize = sub_y * 2 + sub_x;
let mask: usize = 1 << offset;
let blocktad_char: char = BLOCKTAD_CHAR_LUT[mask];
let rich_text: RichText = RichText::new(blocktad_char.to_string())
.with_fg(color)
.with_cell_format(CellFormat::Blocktad);
draw_text(engine, layer_index, cell_x, cell_y, rich_text);
}
pub fn draw_twoxel(engine: &mut Engine, layer_index: LayerIndex, x: f32, y: f32, color: Color) {
let cell_x: i16 = x.floor() as i16;
let cell_y: i16 = y.floor() as i16;
let sub_y_float: f32 = (y - cell_y as f32) * 2.0;
let sub_y: usize = sub_y_float.floor().clamp(0.0, 1.0) as usize;
let half_block: char = match sub_y {
0 => 'โ',
1 => 'โ',
_ => panic!("Twoxel 'sub_y': {sub_y} falls out of range."),
};
let rich_text: RichText = RichText::new(half_block.to_string())
.with_fg(color)
.with_cell_format(CellFormat::Twoxel);
draw_text(engine, layer_index, cell_x, cell_y, rich_text)
}
pub fn draw_fps_counter(engine: &mut Engine, layer_index: LayerIndex, x: i16, y: i16) {
let text: String = format!("FPS: {:2.0}", get_fps(engine));
draw_text(engine, layer_index, x, y, text);
}