use glfw::*;
use glow::HasContext;
use impellers::*;
#[allow(unused)]
pub struct SdlGlImpellerFrameWork {
pub ttx: TypographyContext,
pub style: ParagraphStyle,
pub itx: impellers::Context,
pub glow_ctx: glow::Context,
pub receiver: GlfwReceiver<(f64, WindowEvent)>,
pub window: PWindow,
pub gtx: Glfw,
pub events: Vec<WindowEvent>,
}
impl Default for SdlGlImpellerFrameWork {
fn default() -> Self {
Self::new()
}
}
#[allow(unused)]
pub const DOG_BYTES: &[u8] = include_bytes!("dog.jpg");
type UserCallback = Box<dyn FnMut(&mut SdlGlImpellerFrameWork) -> Option<DisplayList>>;
impl SdlGlImpellerFrameWork {
pub fn new() -> Self {
let mut gtx = init(fail_on_errors).expect("failed to init glfw");
gtx.window_hint(WindowHint::ContextVersionMajor(4));
gtx.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
gtx.window_hint(WindowHint::SRgbCapable(true));
gtx.window_hint(WindowHint::StencilBits(Some(8)));
gtx.window_hint(WindowHint::ScaleToMonitor(true));
let (mut window, ev_receiver) = gtx
.create_window(800, 600, "glfw opengl impeller", WindowMode::Windowed)
.unwrap();
window.make_current();
window.set_all_polling(true);
let itx = unsafe { impellers::Context::new_opengl_es(|s| window.get_proc_address(s) as _) }
.unwrap();
let glow_ctx =
unsafe { glow::Context::from_loader_function(|s| window.get_proc_address(s) as _) };
unsafe {
let (width, height) = window.get_framebuffer_size();
glow_ctx.viewport(0, 0, width, height);
}
let ttx = TypographyContext::default();
let mut style = ParagraphStyle::default();
style.set_font_size(24.0);
style.set_font_family("Roboto");
style.set_font_weight(FontWeight::Bold);
let mut paint = Paint::default();
paint.set_color(Color::LIGHT_SKY_BLUE);
style.set_foreground(&paint);
Self {
ttx,
style,
glow_ctx,
itx,
window,
receiver: ev_receiver,
gtx,
events: vec![],
}
}
pub fn enter_event_loop(
mut self,
dl: Option<DisplayList>,
mut user_callback: Option<UserCallback>,
) {
let mut previous_instant = std::time::Instant::now();
let mut current_frame = 0;
let mut fps = 0;
let mut vsync = true;
while !self.window.should_close() {
{
if previous_instant.elapsed().as_secs_f64() >= 1.0 {
fps = current_frame;
current_frame = 0;
previous_instant = std::time::Instant::now();
}
current_frame += 1;
}
self.events.clear();
self.gtx.poll_events();
for (_, event) in flush_messages(&self.receiver) {
match &event {
WindowEvent::Close => {
self.window.set_should_close(true);
}
WindowEvent::FramebufferSize(w, h) => {
unsafe {
self.glow_ctx.viewport(0, 0, *w, *h);
}
println!("window resized to {}x{}", w, h);
}
WindowEvent::Key(Key::Space, _, Action::Release, _) => {
vsync = !vsync;
println!("setting vsync to {vsync}");
self.gtx.set_swap_interval(if vsync {
SwapInterval::Sync(1)
} else {
SwapInterval::None
});
}
_ => {}
}
self.events.push(event);
}
let (width, height) = self.window.get_framebuffer_size();
let mut surface = unsafe {
self.itx.wrap_fbo(
0,
PixelFormat::RGBA8888,
ISize::new(width.into(), height.into()),
)
}
.expect("failed to wrap window's framebuffer");
let mut dl_builder = DisplayListBuilder::new(Some(&Rect::from_size(
[width as f32, height as f32].into(),
)));
if let Some(dl) = dl.as_ref() {
dl_builder.draw_display_list(dl, 1.0);
}
if let Some(cb) = user_callback.as_mut() {
if let Some(display_list) = cb(&mut self) {
dl_builder.draw_display_list(&display_list, 1.0);
}
}
{
let mut para_builder = ParagraphBuilder::new(&self.ttx).unwrap();
para_builder.push_style(&self.style);
para_builder.add_text(&format!("avg fps: {fps}"));
let para = para_builder.build(1000.0).unwrap();
dl_builder.draw_paragraph(¶, Point::origin());
}
surface
.draw_display_list(&dl_builder.build().unwrap())
.unwrap();
self.window.swap_buffers();
}
}
}
#[allow(unused)]
pub fn main() {
unimplemented!("this is a common module for other examples to use")
}