use glfw::Context as _;
use super::data::Color;
use super::input::Event;
pub struct Window {
glfw: glfw::Glfw,
#[expect(
clippy::struct_field_names,
reason = "needed to distinguish from glfw field"
)]
glfw_window: glfw::PWindow,
glfw_events: glfw::GlfwReceiver<(f64, glfw::WindowEvent)>,
}
impl Window {
#[inline]
pub fn new(width: u32, height: u32, title: &str) -> Result<Window, String> {
use glfw::fail_on_errors;
let mut glfw = glfw::init(fail_on_errors!())
.map_err(|err| format!("Realms: failed to initialise glfw: {err}"))?;
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
glfw::OpenGlProfileHint::Core,
));
#[cfg(target_os = "macos")]
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
let (mut glfw_window, glfw_events) = glfw
.create_window(width, height, title, glfw::WindowMode::Windowed)
.ok_or("Realms: failed to create glfw window")?;
glfw_window.make_current();
glfw_window.set_all_polling(true);
gl::load_with(|symbol| glfw_window.get_proc_address(symbol).cast());
Ok(Window {
glfw,
glfw_window,
glfw_events,
})
}
#[inline]
#[must_use]
pub fn is_running(&self) -> bool {
!self.glfw_window.should_close()
}
#[inline]
pub fn close(&mut self) {
self.glfw_window.set_should_close(true);
}
#[inline]
pub fn new_frame(&mut self) {
self.glfw_window.swap_buffers();
}
#[inline]
pub fn fill(&mut self, color: Color) {
let (r, g, b, a) = color.gl();
unsafe {
gl::ClearColor(r, g, b, a);
}
unsafe {
gl::Clear(gl::COLOR_BUFFER_BIT);
}
}
#[inline]
pub fn events(&mut self) -> Vec<Event> {
let mut events = Vec::new();
self.glfw.poll_events();
for (_, glfw_event) in glfw::flush_messages(&self.glfw_events) {
let event = Event::from_glfw(glfw_event);
events.push(event);
}
for event in &events {
self.handle_event(event);
}
events
}
#[expect(
clippy::unused_self,
reason = "this function will be used in the future and will require the self parameter"
)]
#[expect(
clippy::needless_pass_by_ref_mut,
reason = "in the future, the window's state may need to be updated"
)]
#[inline]
fn handle_event(&mut self, event: &Event) {
#[expect(
clippy::single_match,
reason = "more events will be handled in the future"
)]
#[expect(
clippy::wildcard_enum_match_arm,
reason = "if more Events are added, we just want to ignore them"
)]
match *event {
Event::ResizeWindow(width, height) => unsafe { gl::Viewport(0, 0, width, height) },
_ => {}
};
}
}