1use super::KeyState;
2use super::sprite::RustConsoleSprite;
3
4use std::io::Error;
5use std::mem::{swap, MaybeUninit};
6
7pub struct RustConsole {
8 width: usize,
9 height: usize,
10 font_width: i16,
11 font_height: i16,
12 keys: [KeyState; 256],
13 old_key_states: [i16; 256],
14 new_key_states: [i16; 256]
15}
16
17impl RustConsole {
18 pub const FG_BLACK: u16 = 0x0000;
19 pub const FG_DARK_BLUE: u16 = 0x0001;
20 pub const FG_DARK_GREEN: u16 = 0x0002;
21 pub const FG_DARK_CYAN: u16 = 0x0003;
22 pub const FG_DARK_RED: u16 = 0x0004;
23 pub const FG_DARK_MAGENTA: u16 = 0x0005;
24 pub const FG_DARK_YELLOW: u16 = 0x0006;
25 pub const FG_GREY: u16 = 0x0007;
26 pub const FG_DARK_GREY: u16 = 0x0008;
27 pub const FG_BLUE: u16 = 0x0009;
28 pub const FG_GREEN: u16 = 0x000a;
29 pub const FG_CYAN: u16 = 0x000b;
30 pub const FG_RED: u16 = 0x000c;
31 pub const FG_MAGENTA: u16 = 0x000d;
32 pub const FG_YELLOW: u16 = 0x000e;
33 pub const FG_WHITE: u16 = 0x000f;
34 pub const BG_BLACK: u16 = 0x0000;
35 pub const BG_DARK_BLUE: u16 = 0x0010;
36 pub const BG_DARK_GREEN: u16 = 0x0020;
37 pub const BG_DARK_CYAN: u16 = 0x0030;
38 pub const BG_DARK_RED: u16 = 0x0040;
39 pub const BG_DARK_MAGENTA: u16 = 0x0050;
40 pub const BG_DARK_YELLOW: u16 = 0x0060;
41 pub const BG_GREY: u16 = 0x0070;
42 pub const BG_DARK_GREY: u16 = 0x0080;
43 pub const BG_BLUE: u16 = 0x0090;
44 pub const BG_GREEN: u16 = 0x00a0;
45 pub const BG_CYAN: u16 = 0x00b0;
46 pub const BG_RED: u16 = 0x00c0;
47 pub const BG_MAGENTA: u16 = 0x00d0;
48 pub const BG_YELLOW: u16 = 0x00e0;
49 pub const BG_WHITE: u16 = 0x00f0;
50
51 pub const PIXEL_SOLID: char = '\u{2588}';
52 pub const PIXEL_THREEQUARTER: char = '\u{2593}';
53 pub const PIXEL_HALF: char = '\u{2592}';
54 pub const PIXEL_QUARTER: char = '\u{2591}';
55
56 pub const VK_UP: u32 = 38u32;
57 pub const VK_DOWN: u32 = 40u32;
58 pub const VK_LEFT: u32 = 37u32;
59 pub const VK_RIGHT: u32 = 39u32;
60
61 pub(crate) fn new(width: usize, height: usize, font_width: i16, font_height: i16) -> Result<RustConsole, Error> {
62 Ok(RustConsole {
63 width,
64 height,
65 font_width,
66 font_height,
67 keys: [KeyState { pressed: false, released: false, held: false }; 256],
68 old_key_states: unsafe { MaybeUninit::<[i16; 256]>::zeroed().assume_init() },
69 new_key_states: unsafe { MaybeUninit::<[i16; 256]>::zeroed().assume_init() }
70 })
71 }
72
73 pub(crate) fn write_output(&mut self) {}
74
75 pub(crate) fn update_key_states(&mut self) {
76 for v_key in 0..256 {
77 self.new_key_states[v_key] = 0;
78
79 self.keys[v_key].pressed = false;
80 self.keys[v_key].released = false;
81
82 if self.new_key_states[v_key] != self.old_key_states[v_key] {
83 if self.new_key_states[v_key] != 0 {
84 self.keys[v_key].pressed = !self.keys[v_key].held;
85 self.keys[v_key].held = true;
86 } else {
87 self.keys[v_key].released = true;
88 self.keys[v_key].held = false;
89 }
90 }
91
92 self.old_key_states[v_key] = self.new_key_states[v_key];
93 }
94 }
95
96 pub(crate) fn flush_input_events(&self) {}
97
98 pub(crate) fn handle_input_events(&mut self) {}
99
100 pub fn width(&self) -> usize { self.width }
101
102 pub fn height(&self) -> usize { self.height }
103
104 pub fn font_width(&self) -> i16 { self.font_width }
105
106 pub fn font_height(&self) -> i16 { self.font_height }
107
108 pub fn key(&self, v_key: usize) -> KeyState { self.keys[v_key] }
109
110 pub fn set_title(&self, _title: String) {}
111
112 pub fn resize(&mut self, new_width: usize, new_height: usize, new_font_width: i16, new_font_height: i16) {
113 self.flush_input_events();
114
115 self.width = new_width;
116 self.height = new_height;
117 self.font_width = new_font_width;
118 self.font_height = new_font_height;
119 }
120
121 pub fn clear(&mut self) {}
122
123 pub fn draw(&mut self, _x: usize, _y: usize, _c: char, _col: u16) {}
124
125 pub fn fill(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, c: char, col: u16) {
126 for x in x1..x2 {
127 for y in y1..y2 {
128 self.draw(x, y, c, col);
129 }
130 }
131 }
132
133 pub fn draw_string(&mut self, _x: usize, _y: usize, _s: &str, _col: u16) {}
134
135 pub fn draw_string_alpha(&mut self, _x: usize, _y: usize, _s: &str, _col: u16) {}
136
137 pub fn draw_line(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, c: char, col: u16) {
138 let dx = x2 as isize - x1 as isize;
139 let dy = y2 as isize - y1 as isize;
140 let dx1 = dx.abs();
141 let dy1 = dy.abs();
142 let mut px = 2 * dy1 - dx1;
143 let mut py = 2 * dx1 - dy1;
144 if dy1 <= dx1 {
145 let (mut x, mut y, xe) = if dx >= 0 {
146 (x1, y1, x2)
147 } else {
148 (x2, y2, x1)
149 };
150
151 self.draw(x, y, c, col);
152
153 for _i in x..xe {
154 x += 1;
155 if px < 0 {
156 px = px + 2 * dy1;
157 } else {
158 if (dx < 0 && dy < 0) || (dx > 0 && dy > 0) {
159 y += 1;
160 } else {
161 y -= 1;
162 }
163 px = px + 2 * (dy1 - dx1);
164 }
165 self.draw(x, y, c, col);
166 }
167 } else {
168 let (mut x, mut y, ye) = if dy >= 0 {
169 (x1, y1, y2)
170 } else {
171 (x2, y2, y1)
172 };
173
174 self.draw(x, y, c, col);
175
176 for _i in y..ye {
177 y += 1;
178 if py <= 0 {
179 py = py + 2 * dx1;
180 } else {
181 if (dx < 0 && dy < 0) || (dx > 0 && dy > 0) {
182 x += 1;
183 } else {
184 x -= 1;
185 }
186 py = py + 2 * (dx1 - dy1);
187 }
188 self.draw(x, y, c, col);
189 }
190 }
191 }
192
193 pub fn draw_triangle(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, x3: usize, y3: usize, c: char, col: u16) {
194 self.draw_line(x1, y1, x2, y2, c, col);
195 self.draw_line(x2, y2, x3, y3, c, col);
196 self.draw_line(x3, y3, x1, y1, c, col);
197 }
198
199 pub fn fill_triangle(&mut self, mut x1: usize, mut y1: usize, mut x2: usize, mut y2: usize, mut x3: usize, mut y3: usize, c: char, col: u16) {
200 let mut changed1 = false;
201 let mut changed2 = false;
202
203 if y1 > y2 {
205 swap(&mut y1, &mut y2);
206 swap(&mut x1, &mut x2);
207 }
208 if y1 > y3 {
209 swap(&mut y1, &mut y3);
210 swap(&mut x1, &mut x3);
211 }
212 if y2 > y3 {
213 swap(&mut y2, &mut y3);
214 swap(&mut x2, &mut x3);
215 }
216
217 let mut t1x = x1 as isize;
219 let mut t2x = x1 as isize;
220 let mut y = y1;
221 let mut dx1 = x2 as isize - x1 as isize;
222 let signx1 = if dx1 < 0 {
223 dx1 = -dx1;
224 -1
225 } else {
226 1
227 };
228 let mut dy1 = y2 as isize - y1 as isize;
229
230 let mut dx2 = x3 as isize - x1 as isize;
231 let signx2 = if dx2 < 0 {
232 dx2 = -dx2;
233 -1
234 } else {
235 1
236 };
237 let mut dy2 = y3 as isize - y1 as isize;
238
239 if dy1 > dx1 {
240 swap(&mut dx1, & mut dy1);
241 changed1 = true;
242 }
243 if dy2 > dx2 {
244 swap(&mut dy2, &mut dx2);
245 changed2 = true;
246 }
247
248 let mut e2 = dx2 >> 1;
249 if y1 != y2 { let mut e1 = dx1 >> 1;
251
252 for mut i in 0..dx1 {
253 let mut t1xp = 0;
254 let mut t2xp = 0;
255 let (mut minx, mut maxx) = if t1x < t2x {
256 (t1x, t2x)
257 } else {
258 (t2x, t1x)
259 };
260 'first_line_1: while i < dx1 {
262 i += 1;
263 e1 += dy1;
264 while e1 >= dx1 {
265 e1 -= dx1;
266 if changed1 {
267 t1xp = signx1;
268 } else {
269 break 'first_line_1;
270 }
271 }
272 if changed1 {
273 break 'first_line_1;
274 } else {
275 t1x += signx1;
276 }
277 }
278
279 'second_line_1: loop {
281 e2 += dy2;
282 while e2 >= dx2 {
283 e2 -= dx2;
284 if changed2 {
285 t2xp = signx2;
286 } else {
287 break 'second_line_1;
288 }
289 }
290 if changed2 {
291 break 'second_line_1;
292 } else {
293 t2x += signx2;
294 }
295 }
296
297 if minx > t1x {
298 minx = t1x;
299 }
300 if minx > t2x {
301 minx = t2x;
302 }
303 if maxx < t1x {
304 maxx = t1x;
305 }
306 if maxx < t2x {
307 maxx = t2x;
308 }
309 for j in minx..=maxx {
311 self.draw(j as usize, y, c, col);
312 }
313
314 if !changed1 {
316 t1x += signx1;
317 }
318 t1x += t1xp;
319 if !changed2 {
320 t2x += signx2;
321 }
322 t2x += t2xp;
323 y += 1;
324 if y == y2 {
325 break;
326 }
327 }
328 }
329
330 dx1 = x3 as isize - x2 as isize;
332 let signx1 = if dx1 < 0 {
333 dx1 = -dx1;
334 -1
335 } else {
336 1
337 };
338 dy1 = y3 as isize - y2 as isize;
339 t1x = x2 as isize;
340
341 if dy1 > dx1 {
342 swap(&mut dy1, &mut dx1);
343 changed1 = true;
344 } else {
345 changed1 = false;
346 }
347 let mut e1 = dx1 >> 1;
348
349 for mut i in 0..=dx1 {
350 let mut t1xp = 0;
351 let mut t2xp = 0;
352 let (mut minx, mut maxx) = if t1x < t2x {
353 (t1x, t2x)
354 } else {
355 (t2x, t1x)
356 };
357 'first_line_2: while i < dx1 {
359 e1 += dy1;
360 while e1 >= dx1 {
361 e1 -= dx1;
362 if changed1 {
363 t1xp = signx1;
364 break;
365 } else {
366 break 'first_line_2;
367 }
368 }
369 if changed1 {
370 break 'first_line_2;
371 } else {
372 t1x += signx1;
373 }
374 if i < dx1 {
375 i += 1;
376 }
377 }
378
379 'second_line_2: while t2x != x3 as isize {
381 e2 += dy2;
382 while e2 >= dx2 {
383 e2 -= dx2;
384 if changed2 {
385 t2xp = signx2;
386 } else {
387 break 'second_line_2;
388 }
389 }
390 if changed2 {
391 break 'second_line_2;
392 } else {
393 t2x += signx2;
394 }
395 }
396
397 if minx > t1x {
398 minx = t1x;
399 }
400 if minx > t2x {
401 minx = t2x;
402 }
403 if maxx < t1x {
404 maxx = t1x;
405 }
406 if maxx < t2x {
407 maxx = t2x;
408 }
409 for j in minx..=maxx {
411 self.draw(j as usize, y, c, col);
412 }
413
414 if !changed1 {
416 t1x += signx1;
417 }
418 t1x += t1xp;
419 if !changed2 {
420 t2x += signx2;
421 }
422 t2x += t2xp;
423 y += 1;
424 if y > y3 {
425 return;
426 }
427 }
428 }
429
430 pub fn draw_circle(&mut self, xc: usize, yc: usize, r: usize, c: char, col: u16) {
431 let mut x = 0;
432 let mut y = r;
433 let mut p = 3 - 2 * r as isize;
434 if r == 0 { return; }
435
436 while y >= x {
437 self.draw(xc - x, yc - y, c, col); self.draw(xc - y, yc - x, c, col); self.draw(xc + y, yc - x, c, col); self.draw(xc + x, yc - y, c, col); self.draw(xc - x, yc + y, c, col); self.draw(xc - y, yc + x, c, col); self.draw(xc + y, yc + x, c, col); self.draw(xc + x, yc + y, c, col); if p < 0 {
446 p += 4 * x as isize + 6;
447 x += 1;
448 } else {
449 p += 4 * (x as isize - y as isize) + 10;
450 x += 1;
451 y -= 1;
452 }
453 }
454 }
455
456 pub fn fill_circle(&mut self, xc: usize, yc: usize, r: usize, c: char, col: u16) {
457 let mut x = 0;
458 let mut y = r;
459 let mut p = 3 - 2 * r as isize;
460 if r == 0 { return; }
461
462 while y >= x {
463 for i in xc - x..=xc + x {
464 self.draw(i, yc - y, c, col);
465 }
466 for i in xc - y..=xc + y {
467 self.draw(i, yc - x, c, col);
468 }
469 for i in xc - x..=xc + x {
470 self.draw(i, yc + y, c, col);
471 }
472 for i in xc - y..=xc + y {
473 self.draw(i, yc + x, c, col);
474 }
475
476 if p < 0 {
477 p += 4 * x as isize + 6;
478 x += 1;
479 } else {
480 p += 4 * (x as isize - y as isize) + 10;
481 x += 1;
482 y -= 1;
483 }
484 }
485 }
486
487 pub fn draw_sprite(&mut self, x: usize, y: usize, sprite: &RustConsoleSprite) {
488 for i in 0..sprite.width() {
489 for j in 0..sprite.height() {
490 if sprite.get_glyph(i, j) != ' ' {
491 self.draw(x + i, y + j, sprite.get_glyph(i, j), sprite.get_color(i, j));
492 }
493 }
494 }
495 }
496}