demo_gl/
demo_gl.rs

1use glutin::event::{Event, WindowEvent};
2use glutin::event_loop::ControlFlow;
3use std::os::raw::c_char;
4
5use thyme::{bench};
6
7mod demo;
8
9const OPENGL_MAJOR_VERSION: u8 = 3;
10const OPENGL_MINOR_VERSION: u8 = 2;
11
12/// A basic RPG character sheet, using the "plain" OpenGL backend.
13/// This file contains the application setup code and wgpu specifics.
14/// the `demo.rs` file contains the Thyme UI code and logic.
15/// A simple party creator and character sheet for an RPG.
16fn main() -> Result<(), Box<dyn std::error::Error>> {
17    // initialize our very basic logger so error messages go to stdout
18    thyme::log::init(log::Level::Warn).unwrap();
19
20    // create glium display
21    let event_loop = glutin::event_loop::EventLoop::new();
22    let window_builder = glutin::window::WindowBuilder::new()
23        .with_title("Hello world!")
24        .with_inner_size(glutin::dpi::LogicalSize::new(1280.0, 720.0));
25
26    let windowed_context = glutin::ContextBuilder::new()
27        .with_gl(glutin::GlRequest::Specific(
28            glutin::Api::OpenGl,
29            (OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION),
30        ))
31        .build_windowed(window_builder, &event_loop)?;
32
33    let windowed_context = unsafe {
34        windowed_context
35            .make_current().map_err(|(_context, e)| e)?
36    };
37
38    {
39        let gl_context = windowed_context.context();
40        gl::load_with(|ptr| gl_context.get_proc_address(ptr) as *const _)
41    }
42
43    // create thyme backend
44    let mut renderer = thyme::GLRenderer::new();
45    let mut context_builder = thyme::ContextBuilder::with_defaults();
46
47    demo::register_assets(&mut context_builder);
48
49    let window_size = [1280.0, 720.0];
50    let mut io = thyme::WinitIo::new(&event_loop, window_size.into())?;
51    let mut context = context_builder.build(&mut renderer, &mut io)?;
52    let mut party = demo::Party::default();
53
54    let mut last_frame = std::time::Instant::now();
55    let frame_time = std::time::Duration::from_millis(16);
56
57    // run main loop
58    event_loop.run(move |event, _, control_flow| match event {
59        Event::MainEventsCleared => {
60            if std::time::Instant::now() > last_frame + frame_time {
61                windowed_context.window().request_redraw();
62            }
63            *control_flow = ControlFlow::WaitUntil(last_frame + frame_time);
64        }
65        Event::RedrawRequested(_) => {
66            last_frame = std::time::Instant::now();
67
68            party.check_context_changes(&mut context, &mut renderer);
69
70            renderer.clear_color(0.5, 0.5, 0.5, 1.0);
71
72            bench::run("thyme", || {
73                windowed_context.window().set_cursor_visible(!party.theme_has_mouse_cursor());
74
75                let mut ui = context.create_frame();
76
77                bench::run("frame", || {
78                    demo::build_ui(&mut ui, &mut party);
79                });
80
81                bench::run("draw", || {
82                    renderer.draw_frame(ui);
83                });
84            });
85
86            windowed_context.swap_buffers().unwrap();
87        }
88        Event::WindowEvent {
89            event: WindowEvent::CloseRequested,
90            ..
91        } => *control_flow = ControlFlow::Exit,
92        event => {
93            io.handle_event(&mut context, &event);
94        }
95    })
96}
97
98// this is passed as a fn pointer to gl::DebugMessageCallback
99// and cannot be marked as an "unsafe extern"
100#[no_mangle]
101#[allow(clippy::not_unsafe_ptr_arg_deref)]
102pub extern "system" fn debug_callback(
103    _: gl::types::GLenum,
104    err_type: gl::types::GLenum,
105    id: gl::types::GLuint,
106    severity: gl::types::GLenum,
107    _: gl::types::GLsizei,
108    message: *const c_char,
109    _: *mut std::ffi::c_void,
110) {
111    match err_type {
112        gl::DEBUG_TYPE_ERROR | gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR => unsafe {
113            let err_text = std::ffi::CStr::from_ptr(message);
114            println!(
115                "Type: {:?} ID: {:?} Severity: {:?}:\n  {:#?}",
116                err_type,
117                id,
118                severity,
119                err_text.to_str().unwrap()
120            );
121        },
122        _ => {}
123    }
124}