diff --git a/examples/glutin_breakout.rs b/examples/glutin_breakout.rs new file mode 100644 index 0000000..d4aff19 --- /dev/null +++ b/examples/glutin_breakout.rs @@ -0,0 +1,46 @@ +extern crate mini_gl_fb; + +use mini_gl_fb::{glutin, GlutinBreakout}; + +use glutin::GlContext; + +fn main() { + let mut fb = mini_gl_fb::gotta_go_fast("Hello world!", 800.0, 600.0); + let buffer = vec![[128u8, 0, 0, 255]; 800 * 600]; + fb.update_buffer(&buffer); + + let GlutinBreakout { + mut events_loop, + gl_window, + mut fb, + } = fb.glutin_breakout(); + + let mut running = true; + while running { + events_loop.poll_events(|event| { + use glutin::{Event, ElementState, VirtualKeyCode}; + use glutin::WindowEvent::*; + + match event { + Event::WindowEvent { event: CloseRequested, .. } => { + running = false; + } + Event::WindowEvent { event: KeyboardInput { input, .. }, .. } => { + if let Some(k) = input.virtual_keycode { + if k == VirtualKeyCode::Escape && input.state == ElementState::Released { + running = false; + } + } + } + Event::WindowEvent { event: Resized(logical_size), .. } => { + let dpi_factor = gl_window.get_hidpi_factor(); + gl_window.resize(logical_size.to_physical(dpi_factor)); + } + _ => {} + } + }); + + fb.redraw(); + gl_window.swap_buffers().unwrap(); + } +} diff --git a/src/core.rs b/src/core.rs index 5aca375..18799da 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,5 @@ use config::Config; +use breakout::GlutinBreakout; use rustic_gl; @@ -155,11 +156,19 @@ impl Internal { } }); if redraw { - self.fb.draw(|_| {}); + self.fb.redraw(); self.gl_window.swap_buffers().unwrap(); } } } + + pub fn glutin_breakout(self) -> GlutinBreakout { + GlutinBreakout { + events_loop: self.events_loop, + gl_window: self.gl_window, + fb: self.fb, + } + } } /// Provides the drawing functionality. @@ -173,6 +182,8 @@ impl Internal { /// exposed, if you need something in a pinch you can dig in easily and make it happen. /// /// The internal fields may change. +/// +/// TODO: Possibly create a FramebufferInternal struct? pub struct Framebuffer { pub buffer_width: i32, pub buffer_height: i32, @@ -230,7 +241,15 @@ impl Framebuffer { // TODO: resize_buffer - fn draw(&mut self, f: F) { + pub fn redraw(&mut self) { + self.draw(|_| {}) + } + + /// Draw the quad to the active context. Optionally issue other commands after binding + /// everything but before + /// + /// You probably want `redraw` (equivalent to `.draw(|_| {})`). + pub fn draw(&mut self, f: F) { unsafe { gl::UseProgram(self.program); gl::BindVertexArray(self.vao); @@ -244,7 +263,7 @@ impl Framebuffer { } } - fn relink_program(&mut self) { + pub fn relink_program(&mut self) { unsafe { gl::DeleteProgram(self.program); self.program = build_program(&[ diff --git a/src/lib.rs b/src/lib.rs index cc47615..da8029f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,8 +67,9 @@ pub extern crate gl; mod config; mod core; -// mod breakout; +mod breakout; +pub use breakout::GlutinBreakout; pub use config::Config; pub use core::{Internal, BufferFormat}; @@ -188,6 +189,18 @@ impl MiniGlFb { self.internal.persist_and_redraw(redraw); } + /// Need full access to Glutin's event handling? No problem! + /// + /// Hands you the event loop and the window we created, so you can handle events however you + /// want, and the Framebuffer, so you can still draw easily! + /// + /// **IMPORTANT:** You should make sure to render something before swapping buffers or **the + /// window may flash violently**. You can call `fb.redraw()` directly before if you are unsure + /// that an OpenGL draw call was issued. `fb.update_buffer` will typically issue a draw call. + pub fn glutin_breakout(self) -> GlutinBreakout { + self.internal.glutin_breakout() + } + // TODO: resize_buffer // TODO: set_resizable // TODO: change_buffer_format