1static DEFAULT_HEIGHT: u32 = 900;
8static DEFAULT_WIDTH: u32 = 1600;
9
10extern crate gl;
11extern crate glfw;
12
13use color::Color;
14use draw;
15use draw::{Drawable, DrawableMut, Drawer};
16use event::{EventReceiver, EventType};
17use glfw::Context;
18use nalgebra;
19use nalgebra::Matrix4;
20use rect::Rect;
21use std::rc::Rc;
22use std::sync::mpsc::Receiver;
23use std::sync::Mutex;
24use view::View;
25use Vector;
26
27static DEFAULT_FPS: u32 = 60;
28
29lazy_static! {
30 static ref DEFAULT_DELTA: f64 = 1.0 / f64::from(DEFAULT_FPS);
31}
32
33pub struct Window {
36 pub height: u32,
37 pub width: u32,
38 event: Rc<Receiver<(f64, glfw::WindowEvent)>>,
39 pub(super) win: glfw::Window,
40 clear_color: Color,
41 already_init: bool,
42 view: View,
43 fps_limit: u32,
44}
45
46lazy_static! {
47 static ref GLFW_INSTANCE: Mutex<glfw::Glfw> =
48 Mutex::new(glfw::init(glfw::FAIL_ON_ERRORS).unwrap());
49}
50
51impl<'a> Window {
53 pub fn new(width: u32, height: u32, name: &str) -> Window {
55 let mut glfw = GLFW_INSTANCE.lock().unwrap();
58
59 glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
60 glfw.window_hint(glfw::WindowHint::OpenGlProfile(
61 glfw::OpenGlProfileHint::Core,
62 ));
63
64 let (mut win, evt) = glfw
68 .create_window(width, height, name, glfw::WindowMode::Windowed)
69 .unwrap();
70
71 gl::load_with(|s| win.get_proc_address(s) as *const _);
73 win.set_cursor_mode(glfw::CursorMode::Normal);
74
75 unsafe {
76 gl::Viewport(0, 0, width as i32, height as i32);
77 gl::Enable(gl::CULL_FACE);
78 gl::Enable(gl::BLEND);
79 gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
80 }
81
82 glfw.set_swap_interval(glfw::SwapInterval::Sync(1));
83
84 Window {
85 view: View::from(Rect::new(0.0, 0.0, width as f32, height as f32)),
86 height,
87 width,
88 win,
89 event: Rc::new(evt),
90 clear_color: Color::new(1.0, 1.0, 1.0),
91 already_init: true,
92 fps_limit: self::DEFAULT_FPS,
93 }
94 }
95
96 pub fn set_mouse_pos<T: nalgebra::Scalar + Into<f32>>(&mut self, vec: Vector<T>) {
97 self.win
98 .set_cursor_pos(f64::from(vec.x.into()), f64::from(vec.y.into()))
99 }
100
101 pub fn poll<T: Into<Option<EventType>>>(&mut self, event: T) {
102 Self::match_event_type(self, event.into(), true);
103 }
104
105 pub fn unpoll<T: Into<Option<EventType>>>(&mut self, event: T) {
106 Self::match_event_type(self, event.into(), false);
107 }
108
109 fn match_event_type(window: &mut Window, event: Option<EventType>, active: bool) {
110 if event.is_none() {
111 window.win.set_all_polling(active);
112 } else {
113 match event.unwrap() {
114 EventType::Key => window.win.set_key_polling(active),
115 EventType::Pos => window.win.set_pos_polling(active),
116 EventType::Close => window.win.set_close_polling(active),
117 EventType::Size => window.win.set_size_polling(active),
118 EventType::Refresh => window.win.set_refresh_polling(active),
119 EventType::Focus => window.win.set_focus_polling(active),
120 EventType::Char => window.win.set_char_polling(active),
121 EventType::CharMods => window.win.set_char_mods_polling(active),
122 EventType::MouseButton => window.win.set_mouse_button_polling(active),
123 EventType::CursorPos => window.win.set_cursor_pos_polling(active),
124 EventType::CursorEnter => window.win.set_cursor_enter_polling(active),
125 EventType::Scroll => window.win.set_scroll_polling(active),
126 EventType::FrameBuffer => window.win.set_framebuffer_size_polling(active),
127 }
128 }
129 }
130
131 pub fn mouse_pos(&self) -> Vector<f32> {
132 let pos = self.win.get_cursor_pos();
133 Vector::new(pos.0 as f32, pos.1 as f32)
134 }
135
136 pub fn hide_cursor(&mut self) {
138 self.win.set_cursor_mode(glfw::CursorMode::Hidden);
139 }
140
141 pub fn disable_cursor(&mut self) {
143 self.win.set_cursor_mode(glfw::CursorMode::Disabled);
144 }
145
146 pub fn enable_cursor(&mut self) {
148 self.win.set_cursor_mode(glfw::CursorMode::Normal);
149 }
150
151 pub fn is_open(&self) -> bool {
153 !self.win.should_close()
154 }
155
156 pub fn poll_events(&mut self) {
158 GLFW_INSTANCE.lock().unwrap().poll_events();
159 }
160
161 pub fn set_clear_color(&mut self, new_color: Color) {
163 self.clear_color = new_color;
164 }
165
166 pub fn close(&mut self) {
168 self.win.set_should_close(true);
169 }
170
171 pub fn clear(&self) {
173 unsafe {
174 gl::ClearColor(
175 self.clear_color.0,
176 self.clear_color.1,
177 self.clear_color.2,
178 self.clear_color.3,
179 );
180 gl::Clear(gl::COLOR_BUFFER_BIT);
181 }
182 }
183
184 pub fn active(&mut self) -> bool {
186 GLFW_INSTANCE
187 .lock()
188 .unwrap()
189 .make_context_current(Some(&self.win));
190 true
191 }
192
193 pub fn set_view(&mut self, view: View) {
194 self.view = view;
195 }
196
197 pub fn display(&mut self) {
199 self.win.swap_buffers();
200 }
201
202 fn init_gl() {
204 unimplemented!();
205 }
206
207 fn set_input_mode(&self, im: &InputMode) {
209 let (mode, value) = im.to_i32();
210 unsafe {
211 glfw::ffi::glfwSetInputMode(self.win.window_ptr(), mode, value);
212 }
213 }
214
215 fn input_mode(&self, im: &InputMode) -> InputMode {
217 unsafe {
218 InputMode::from(glfw::ffi::glfwGetInputMode(
219 self.win.window_ptr(),
220 im.to_i32().0,
221 ))
222 }
223 }
224
225 pub fn view(&self) -> &View {
226 &self.view
227 }
228
229 pub fn view_mut(&mut self) -> &mut View {
230 &mut self.view
231 }
232
233 pub fn set_fps_limit(&mut self, limit: u32) -> u32 {
234 let old = self.fps_limit;
235 self.fps_limit = limit;
236 old
237 }
238
239 pub fn fps_limit(&self) -> u32 {
240 self.fps_limit
241 }
242
243 pub fn event(&self) -> &EventReceiver {
244 &self.event
245 }
246
247 pub fn event_mut(&mut self) -> &mut EventReceiver {
248 &mut self.event
249 }
250}
251
252impl Drawer for Window {
253 fn draw<T: Drawable>(&mut self, drawable: &T) {
254 self.active();
255 drawable.draw(self);
256 }
257
258 #[inline]
259 fn draw_mut<T: DrawableMut>(&mut self, drawable: &mut T) {
260 self.active();
261 drawable.draw_mut(self);
262 }
263
264 #[inline]
265 fn draw_with_context<T: Drawable>(&mut self, drawable: &mut T, context: &mut draw::Context) {
266 self.active();
267 drawable.draw_with_context(context);
268 }
269
270 #[inline]
271 fn draw_with_context_mut<T: DrawableMut>(
272 &mut self,
273 drawable: &mut T,
274 context: &mut draw::Context,
275 ) {
276 self.active();
277 drawable.draw_with_context(context);
278 }
279
280 #[inline]
281 fn get_sizes(&self) -> Vector<f32> {
282 Vector::new(self.width as f32, self.height as f32)
283 }
284
285 #[inline]
286 fn get_center(&self) -> Vector<f32> {
287 let view_pos = self.view().postition();
288 let view_zoom = self.view().get_zoom();
289
290 println!("View pos: {:?}", view_pos);
291 Vector::new(
292 (self.width as f32 / (2.0 * (1.0 / view_zoom))) + view_pos.x,
293 (self.height as f32 / (2.0 * (1.0 / view_zoom))) + view_pos.y,
294 )
295 }
296
297 fn projection(&self) -> &Matrix4<f32> {
298 self.view.projection()
299 }
300}
301
302impl Default for Window {
304 fn default() -> Window {
305 let (mut win, evt) = GLFW_INSTANCE
306 .lock()
307 .unwrap()
308 .create_window(
309 DEFAULT_HEIGHT as u32,
310 DEFAULT_WIDTH as u32,
311 "Gust",
312 glfw::WindowMode::Windowed,
313 )
314 .unwrap();
315
316 gl::load_with(|s| win.get_proc_address(s) as *const _);
317
318 Window {
319 view: View::from(Rect::new(
320 0.0,
321 0.0,
322 DEFAULT_WIDTH as f32,
323 DEFAULT_HEIGHT as f32,
324 )),
325 height: DEFAULT_HEIGHT,
326 width: DEFAULT_WIDTH,
327 win,
328 event: Rc::new(evt),
329 clear_color: Color::new(1.0, 1.0, 1.0),
330 already_init: true,
331 fps_limit: self::DEFAULT_FPS,
332 }
333 }
334}
335
336pub enum InputMode {
337 CursorMode(InputState),
338 StickMouseButtons,
339 StickKeys,
340 NotDefined,
341}
342
343impl InputMode {
344 fn to_i32(&self) -> (i32, i32) {
345 match self {
346 InputMode::CursorMode(a) => (0x0003_3001, a as *const _ as i32),
347 InputMode::StickKeys => (0x0003_3002, 1),
348 InputMode::StickMouseButtons => (0x0003_3003, 1),
349 InputMode::NotDefined => (-1, -1),
350 }
351 }
352}
353
354impl From<i32> for InputMode {
355 fn from(value: i32) -> InputMode {
356 match value {
357 0x0003_3001 => InputMode::CursorMode(InputState::Normal),
358 0x0003_3002 => InputMode::StickKeys,
359 0x0003_3003 => InputMode::StickMouseButtons,
360 _ => InputMode::NotDefined,
361 }
362 }
363}
364
365pub enum InputState {
366 Normal = 0x0003_4001,
367 Hidden = 0x0003_4002,
368 Disable = 0x0003_4003,
369}