1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
use teleia::*;
pub const WIDTH: usize = 64;
pub const HEIGHT: usize = 64;
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub struct Pos {
pub x: i32, pub y: i32,
}
impl Pos {
pub fn new(x: i32, y: i32) -> Self { Self { x, y } }
}
impl std::ops::Add for Pos {
type Output = Pos;
fn add(self, rhs: Self) -> Self { Self {x: self.x + rhs.x, y: self.y + rhs.y } }
}
#[derive(Debug, Clone)]
pub struct CharPair {
pub first: char,
pub second: Option<char>,
}
impl Default for CharPair {
fn default() -> Self {
Self {
first: 'a',
second: Some('b'),
}
}
}
pub struct Layer<T> {
pub data: [T; WIDTH * HEIGHT],
}
impl<T> Layer<T> {
pub fn new() -> Self where T: Default {
Self {
data: [(); WIDTH * HEIGHT].map(|_| T::default()),
}
}
pub fn get(&self, p: Pos) -> Option<&T> {
if p.x < 0 || p.x >= WIDTH as _ || p.y < 0 || p.y >= HEIGHT as _ { return None }
let idx = p.x as usize + p.y as usize * WIDTH;
Some(&self.data[idx])
}
pub fn set(&mut self, p: Pos, x: T) {
if p.x < 0 || p.x >= WIDTH as _ || p.y < 0 || p.y >= HEIGHT as _ { return }
let idx = p.x as usize + p.y as usize * WIDTH;
self.data[idx] = x;
}
}
impl Layer<CharPair> {
pub fn from_str(&mut self, s: &str) {
let chars: Vec<char> = s.chars().collect();
if chars.is_empty() { return }
let mut i: usize = 0;
for row in 0..64 {
for col in 0..64 {
let first = chars[i]; i += 1; i %= chars.len();
let second = Some(chars[i]); i += 1; i %= chars.len();
self.set(Pos::new(col, row), CharPair { first, second });
}
}
}
}
impl Layer<glam::Vec3> {
pub fn from_framebuffer(&mut self, ctx: &context::Context, fb: &framebuffer::Framebuffer) {
fb.get_pixels(ctx, &mut self.data);
}
}
pub struct Terminal {
pub font: font::Bitmap,
pub base_color: Layer<glam::Vec3>,
pub set_color: Layer<glam::Vec3>,
pub set_char: Layer<CharPair>,
}
impl Terminal {
pub fn new(ctx: &context::Context) -> Self {
let mut set_char = Layer::new();
set_char.from_str("lcolonq");
Self {
font: font::Bitmap::from_image(ctx, 6, 12, 96, 72, include_bytes!("assets/fonts/terminus.png")),
base_color: Layer::new(),
set_color: Layer::new(),
set_char,
}
}
pub fn get_color(&self, pos: Pos) -> glam::Vec3 {
if let Some(c) = self.base_color.get(pos) {
c.clone()
} else {
glam::Vec3::new(1.0, 1.0, 1.0)
}
}
pub fn update(&mut self, ctx: &context::Context, fb: &framebuffer::Framebuffer) {
self.base_color.from_framebuffer(ctx, fb);
}
pub fn fill_string(&mut self, s: &str) {
self.set_char.from_str(s);
}
pub fn render(&self, ctx: &context::Context, pos: &glam::Vec2) {
let mut s = String::new();
let mut colors = Vec::new();
for row in 0..64 {
for col in 0..64 {
let pos = Pos::new(col, row);
let new = if let Some(p) = self.set_char.get(pos) {
format!("{}{}", p.first, if let Some(snd) = p.second { snd } else { ' ' })
} else {
String::from(" ")
};
s += &new;
let c = self.get_color(pos);
colors.push(c); colors.push(c);
}
s += "\n";
colors.push(glam::Vec3::new(1.0, 1.0, 1.0));
}
self.font.render_text_helper(ctx, pos, &s, &colors);
}
}
|