1use std::*;
8use std::sync::mpsc;
9use std::collections::HashSet;
10use std::marker::PhantomData;
11
12use crate::types::*;
13use crate::types::events::Event;
14
15extern crate sdl2;
16use self::sdl2::*;
17use self::sdl2::event::Event as SdlEvent;
18use self::sdl2::keyboard::Keycode;
19use self::sdl2::pixels::PixelFormatEnum;
20
21pub struct Renderer<P> {
23 w: u32,
24 h: u32,
25 context: sdl2::Sdl,
26 canvas: render::WindowCanvas,
27 pub event_rx: mpsc::Receiver<events::Event>,
28 event_tx: mpsc::Sender<events::Event>,
29 prev_buttons: HashSet<mouse::MouseButton>,
30 _pixel: PhantomData<P>,
31}
32
33impl <P>Renderer<P> {
34 pub fn new(name: &str, w: u32, h: u32) -> Self {
36 let context = sdl2::init().unwrap();
37 let video_subsystem = context.video().unwrap();
38 let window = video_subsystem
39 .window(name, w, h)
40 .position_centered()
41 .build()
42 .unwrap();
43
44 let canvas = window.into_canvas().software().build().unwrap();
45
46 let (event_tx, event_rx): (mpsc::Sender<events::Event>, mpsc::Receiver<events::Event>) = mpsc::channel();
47
48 let prev_buttons = HashSet::new();
49
50 return Renderer{w, h, context, canvas, event_rx, event_tx, prev_buttons, _pixel: PhantomData};
51 }
52
53 pub fn update(&mut self) -> bool {
56 let mut running = true;
57
58 let mut sdl_events = self.context.event_pump().unwrap();
59
60 for event in sdl_events.poll_iter() {
62 match event {
63 SdlEvent::KeyDown { keycode: Some(Keycode::Escape), .. } |
64 SdlEvent::Quit { .. } => { running = false; },
65 SdlEvent::KeyDown { keycode: Some(Keycode::Up), .. } => { self.event_tx.send(Event::Up).unwrap(); },
66 SdlEvent::KeyDown { keycode: Some(Keycode::Down), .. } => { self.event_tx.send(Event::Down).unwrap(); },
67 SdlEvent::KeyDown { keycode: Some(Keycode::Left), .. } => { self.event_tx.send(Event::Left).unwrap(); },
68 SdlEvent::KeyDown { keycode: Some(Keycode::Right), .. } => { self.event_tx.send(Event::Right).unwrap(); },
69 SdlEvent::KeyDown { keycode: Some(Keycode::Return), .. } => { self.event_tx.send(Event::Select).unwrap(); },
70 SdlEvent::KeyDown { keycode: Some(Keycode::Backspace), .. } => { self.event_tx.send(Event::Back).unwrap(); },
71 _ => {}
72 }
73 }
74
75 let state = sdl_events.mouse_state();
77
78 let buttons = state.pressed_mouse_buttons().collect();
80
81 let new_buttons = &buttons - &self.prev_buttons;
83 let old_buttons = &self.prev_buttons - &buttons;
84
85 if !new_buttons.is_empty() && old_buttons.is_empty() {
86 self.event_tx.send(Event::Click{x: state.x() as usize, y: state.y() as usize}).unwrap();
87 }
88
89 self.prev_buttons = buttons;
90
91 return running;
92 }
93
94 fn render_common(&mut self, data: &[u8]) {
95 let creator = self.canvas.texture_creator();
96 let mut texture = creator.create_texture_target(PixelFormatEnum::RGBA8888, self.w, self.h).unwrap();
97
98 texture.update(None, data, (self.w * 4) as usize).unwrap();
99
100 self.canvas.copy_ex(&texture, None, None, 0.0, None, false, false).unwrap();
101 self.canvas.present();
102 }
103
104
105
106
107}
108
109
110impl Renderer<PixelBW> {
111 pub fn render(&mut self, pixels: &[u8]) {
112 let data = Self::bw_to_rgba32(self.w as usize, self.h as usize, pixels);
113
114 self.render_common(data.as_slice());
115 }
116
117 fn bw_to_rgba32(w: usize, h: usize, pixels: &[u8]) -> Vec<u8> {
119 let size = w * h * 4;
120 let mut data: Vec<u8> = vec![0; size];
121
122 for y in 0..h {
123 let i = y * w / 8;
124 let row = &pixels[i .. i + w / 8];
125
126 for x in 0..w {
127 let pixel_index = x / 8 as usize;
128 let pixel_mask = 1 << (7-(x % 8));
129 let data_index = (y * w + x) * 4 as usize;
130
131 let m = if row[pixel_index] & pixel_mask == 0 {
132 0xFF
133 } else {
134 0x00
135 };
136
137 for i in 0..4 {
138 data[data_index + i] = m;
139 }
140 }
141 }
142
143 data
144 }
145}
146
147
148impl Renderer<PixelRGB24> {
149 pub fn render(&mut self, pixels: &[u8]) {
151 let data = Self::rgb24_to_rgba32(self.w as usize, self.h as usize, &pixels);
152
153 self.render_common(data.as_slice());
154 }
155
156 fn rgb24_to_rgba32(w: usize, h: usize, pixels: &[u8]) -> Vec<u8> {
158 let size = w * h * 4;
159 let mut data: Vec<u8> = vec![0; size];
160
161 for y in 0..h {
162 for x in 0..w {
163 let pixel_index = (y * w + x) * 3;
164 let data_index = (y * w + x) * 4;
165
166 data[data_index+0] = 255;
167 data[data_index+1] = pixels[pixel_index+2];
168 data[data_index+2] = pixels[pixel_index+1];
169 data[data_index+3] = pixels[pixel_index+0];
170 }
171 }
172
173 data
174 }
175}
176
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn test_bw_to_rgba32() {
184 let pixels = [
185 0b1000_0001,
186 0b0100_0010,
187 ];
188 let expected = [
189 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
190 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
191 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
192 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
193 ].to_vec();
194
195
196 let mapped = Renderer::<PixelBW>::bw_to_rgba32(8, 2, &pixels);
197
198 assert_eq!(expected.len(), mapped.len());
199 assert_eq!(expected, mapped);
200 }
201
202 #[test]
203 fn test_rgb24_to_rgba32() {
204 let pixels = [
205 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
206 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
207 ];
208 let expected = [
209 0xff, 0x33, 0x22, 0x11, 0xff, 0x66, 0x55, 0x44,
212 0xff, 0x99, 0x88, 0x77, 0xff, 0xcc, 0xbb, 0xaa,
213 ].to_vec();
214
215
216 let mapped = Renderer::<PixelRGB24>::rgb24_to_rgba32(2, 2, &pixels);
217
218 assert_eq!(expected.len(), mapped.len());
219 assert_eq!(expected, mapped);
220 }
221}