From a3c6970a50a3c769aebce2bcb17cd9d9febe4354 Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Tue, 28 Jan 2025 12:05:07 -0500 Subject: Move to GLFW for transparent clickthrough overlay --- src/context.rs | 11 +++--- src/framebuffer.rs | 2 +- src/lib.rs | 108 ++++++++++++++++++++++++++++++++--------------------- src/state.rs | 41 ++++++++++---------- 4 files changed, 92 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/context.rs b/src/context.rs index ca3ebe3..05d6990 100644 --- a/src/context.rs +++ b/src/context.rs @@ -14,10 +14,11 @@ extern { pub struct Context { pub render_width: f32, pub render_height: f32, - pub window: sdl2::video::Window, + pub glfw: std::cell::RefCell, + pub window: std::cell::RefCell, pub gl: glow::Context, pub emptyvao: glow::VertexArray, - pub timer: sdl2::TimerSubsystem, + pub start_instant: std::time::Instant, } @@ -46,16 +47,16 @@ impl Context { } #[cfg(not(target_arch = "wasm32"))] - pub fn new(sdl: sdl2::Sdl, window: sdl2::video::Window, gl: glow::Context, render_width: f32, render_height: f32) -> Self { + pub fn new(glfw: std::cell::RefCell, window: std::cell::RefCell, gl: glow::Context, render_width: f32, render_height: f32) -> Self { let emptyvao = unsafe { gl.create_vertex_array().expect("failed to initialize vao") }; let ret = Self { render_width, render_height, - window, + glfw, window, gl, emptyvao, - timer: sdl.timer().expect("failed to initialize timer subsystem"), + start_instant: std::time::Instant::now(), }; ret.init(); ret diff --git a/src/framebuffer.rs b/src/framebuffer.rs index f97a967..b3ce859 100644 --- a/src/framebuffer.rs +++ b/src/framebuffer.rs @@ -15,7 +15,7 @@ impl Framebuffer { let (windoww, windowh): (f32, f32) = ctx.window.inner_size().into(); #[cfg(not(target_arch = "wasm32"))] let (windoww, windowh) = { - let (w, h) = ctx.window.size(); + let (w, h) = ctx.window.borrow().get_size(); (w as f32, h as f32) }; let ratio = ctx.compute_upscale(windoww as _, windowh as _) as f32; diff --git a/src/lib.rs b/src/lib.rs index 78202b0..383a28d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,9 @@ use winit::platform::web::WindowExtWebSys; #[cfg(target_arch = "wasm32")] use wasm_bindgen::JsCast; +#[cfg(not(target_arch = "wasm32"))] +use glfw::Context; + static mut CTX: Option<*const context::Context> = None; static mut ST: Option<*mut state::State> = None; static mut G: Option<*mut std::ffi::c_void> = None; @@ -40,7 +43,7 @@ where } #[cfg(not(target_arch = "wasm32"))] -pub async fn run<'a, F, G, Fut>(title: &str, w: u32, h: u32, gnew: F) +pub async fn run<'a, F, G, Fut>(title: &str, w: u32, h: u32, overlay: bool, gnew: F) where Fut: std::future::Future, G: state::Game + 'static, @@ -52,28 +55,46 @@ where log::info!("hello computer, starting up..."); - let (sdl, window, gl, mut event_loop, _gl_context) = { - let sdl = sdl2::init().expect("failed to initialize SDL2"); - let video = sdl.video().expect("failed to initialize SDL2 video"); + let (rglfw, rwindow, gl, events) = { + use glfw::fail_on_errors; + let mut glfw = glfw::init(glfw::fail_on_errors!()).expect("failed to initialize GLFW"); // let gl_attr = video.gl_attr(); // gl_attr.set_context_profile(sdl2::video::GLProfile::Core); // gl_attr.set_context_version(3, 0); - let window = video - .window(title, w as _, h as _) - .opengl() - // .fullscreen_desktop() - .resizable() - .build() - .unwrap(); - let gl_context = window.gl_create_context().unwrap(); + let (mut window, events) = glfw.with_primary_monitor(|glfw, primary| { + if overlay { + let mon = primary.expect("failed to get monitor"); + let mode = mon.get_video_mode().expect("failed to get video mode"); + glfw.window_hint(glfw::WindowHint::RedBits(Some(mode.red_bits))); + glfw.window_hint(glfw::WindowHint::GreenBits(Some(mode.green_bits))); + glfw.window_hint(glfw::WindowHint::BlueBits(Some(mode.blue_bits))); + glfw.window_hint(glfw::WindowHint::RefreshRate(Some(mode.refresh_rate))); + glfw.window_hint(glfw::WindowHint::Resizable(false)); + glfw.window_hint(glfw::WindowHint::Decorated(false)); + glfw.window_hint(glfw::WindowHint::Floating(true)); + glfw.window_hint(glfw::WindowHint::TransparentFramebuffer(true)); + unsafe { + // glfw.window_hint(glfw::WindowHint::MousePassthrough(true)); + glfw::ffi::glfwWindowHint(0x0002000D, 1); // mouse passthrough + } + glfw.create_window(mode.width, mode.height, title, glfw::WindowMode::FullScreen(mon)) + .expect("failed to create window") + } else { + glfw.create_window(w as _, h as _, title, glfw::WindowMode::Windowed) + .expect("failed to create window") + } + }); + window.make_current(); + window.set_key_polling(true); let gl = unsafe { - glow::Context::from_loader_function(|s| video.gl_get_proc_address(s) as *const _) + glow::Context::from_loader_function(|s| window.get_proc_address(s) as *const _) }; - let event_loop = sdl.event_pump().unwrap(); - (sdl, window, gl, event_loop, gl_context) + (glfw, window, gl, events) }; + let glfw = std::cell::RefCell::new(rglfw); + let window = std::cell::RefCell::new(rwindow); - let ctx = Box::leak(Box::new(context::Context::new(sdl, window, gl, w as f32, h as f32))); + let ctx = Box::leak(Box::new(context::Context::new(glfw, window, gl, w as f32, h as f32))); let game = Box::leak(Box::new(gnew(ctx).await)); let st = Box::leak(Box::new(state::State::new(&ctx))); @@ -84,33 +105,34 @@ where } 'running: loop { - for event in event_loop.poll_iter() { + if ctx.window.borrow().should_close() { + log::info!("bye!"); + break 'running; + } + ctx.glfw.borrow_mut().poll_events(); + for (_, event) in glfw::flush_messages(&events) { match event { - sdl2::event::Event::Quit {..} => { - log::info!("bye!"); - break 'running; - }, - sdl2::event::Event::Window { win_event: sdl2::event::WindowEvent::Resized(_, _), .. } => { - st.handle_resize(&ctx); - }, - sdl2::event::Event::Window { win_event: sdl2::event::WindowEvent::FocusLost, .. } => { - st.keys = state::Keys::new(); - }, - sdl2::event::Event::MouseMotion { x, y, .. } => { - st.mouse_moved(&ctx, x as f32, y as f32, game); - }, - sdl2::event::Event::MouseButtonDown {..} => { - st.mouse_pressed(&ctx, game) - }, - sdl2::event::Event::MouseButtonUp {..} => { - st.mouse_released(&ctx) - }, - sdl2::event::Event::KeyDown { keycode: Some(key), repeat: false, .. } => { - st.key_pressed(&ctx, state::Keycode::new(key)) - }, - sdl2::event::Event::KeyUp { keycode: Some(key), repeat: false, .. } => { - st.key_released(&ctx, state::Keycode::new(key)) - }, + // sdl2::event::Event::Window { win_event: sdl2::event::WindowEvent::Resized(_, _), .. } => { + // st.handle_resize(&ctx); + // }, + // sdl2::event::Event::Window { win_event: sdl2::event::WindowEvent::FocusLost, .. } => { + // st.keys = state::Keys::new(); + // }, + // sdl2::event::Event::MouseMotion { x, y, .. } => { + // st.mouse_moved(&ctx, x as f32, y as f32, game); + // }, + // sdl2::event::Event::MouseButtonDown {..} => { + // st.mouse_pressed(&ctx, game) + // }, + // sdl2::event::Event::MouseButtonUp {..} => { + // st.mouse_released(&ctx) + // }, + // sdl2::event::Event::KeyDown { keycode: Some(key), repeat: false, .. } => { + // st.key_pressed(&ctx, state::Keycode::new(key)) + // }, + // sdl2::event::Event::KeyUp { keycode: Some(key), repeat: false, .. } => { + // st.key_released(&ctx, state::Keycode::new(key)) + // }, _ => {}, } } @@ -131,7 +153,7 @@ where } st.run_update(&ctx, game); st.run_render(&ctx, game); - ctx.window.gl_swap_window(); + ctx.window.borrow_mut().swap_buffers(); } // event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll); diff --git a/src/state.rs b/src/state.rs index 03ebf5e..2ac6d4b 100644 --- a/src/state.rs +++ b/src/state.rs @@ -102,17 +102,17 @@ pub type Keycode = winit::keyboard::KeyCode; #[cfg(not(target_arch = "wasm32"))] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Keycode { - pub kc: sdl2::keyboard::Keycode + pub kc: glfw::Key } #[cfg(not(target_arch = "wasm32"))] impl Keycode { - pub fn new(kc: sdl2::keyboard::Keycode) -> Self { Self { kc } } + pub fn new(kc: glfw::Key) -> Self { Self { kc } } } #[cfg(not(target_arch = "wasm32"))] impl Serialize for Keycode { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - (self.kc.into_i32()).serialize(serializer) + (self.kc as i32).serialize(serializer) } } #[cfg(not(target_arch = "wasm32"))] @@ -120,10 +120,8 @@ impl<'de> Deserialize<'de> for Keycode { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { i32::deserialize(deserializer) - .and_then(|x| { - sdl2::keyboard::Keycode::from_i32(x) - .map(|kc| Keycode { kc }) - .ok_or(serde::de::Error::custom("invalid entity flags")) + .map(|x| unsafe { + std::mem::transmute(x) }) } } @@ -161,7 +159,8 @@ pub fn now(ctx: &context::Context) -> Timestamp { #[cfg(not(target_arch = "wasm32"))] pub fn now(ctx: &context::Context) -> Timestamp { - let ms = ctx.timer.ticks64(); + let elapsed = ctx.start_instant.elapsed(); + let ms = elapsed.as_millis(); (ms as f64) / 1000.0 } @@ -184,16 +183,16 @@ pub fn default_keybindings() -> BiHashMap { #[cfg(not(target_arch = "wasm32"))] pub fn default_keybindings() -> BiHashMap { BiHashMap::from_iter(vec![ - (Keycode::new(sdl2::keyboard::Keycode::W), Key::Up), - (Keycode::new(sdl2::keyboard::Keycode::S), Key::Down), - (Keycode::new(sdl2::keyboard::Keycode::A), Key::Left), - (Keycode::new(sdl2::keyboard::Keycode::D), Key::Right), - (Keycode::new(sdl2::keyboard::Keycode::NUM_1), Key::A), - (Keycode::new(sdl2::keyboard::Keycode::NUM_2), Key::B), - (Keycode::new(sdl2::keyboard::Keycode::Q), Key::L), - (Keycode::new(sdl2::keyboard::Keycode::E), Key::R), - (Keycode::new(sdl2::keyboard::Keycode::TAB), Key::Start), - (Keycode::new(sdl2::keyboard::Keycode::SPACE), Key::Select), + (Keycode::new(glfw::Key::W), Key::Up), + (Keycode::new(glfw::Key::S), Key::Down), + (Keycode::new(glfw::Key::A), Key::Left), + (Keycode::new(glfw::Key::D), Key::Right), + (Keycode::new(glfw::Key::Num1), Key::A), + (Keycode::new(glfw::Key::Num2), Key::B), + (Keycode::new(glfw::Key::Q), Key::L), + (Keycode::new(glfw::Key::E), Key::R), + (Keycode::new(glfw::Key::Tab), Key::Start), + (Keycode::new(glfw::Key::Space), Key::Select), ]) } @@ -420,7 +419,7 @@ impl State { #[cfg(target_arch = "wasm32")] let rebind = key == winit::keyboard::KeyCode::F12; #[cfg(not(target_arch = "wasm32"))] - let rebind = key.kc == sdl2::keyboard::Keycode::F12; + let rebind = key.kc == glfw::Key::F12; if rebind { self.keybindings = default_keybindings(); self.rebinding = None; @@ -505,13 +504,13 @@ impl State { pub fn run_render(&mut self, ctx: &context::Context, game: &mut G) where G: Game { self.render_framebuffer.bind(&ctx); - ctx.clear_color(glam::Vec4::new(0.1, 0.1, 0.1, 1.0)); + ctx.clear_color(glam::Vec4::new(0.1, 0.1, 0.1, 0.0)); ctx.clear(); game.render(ctx, self); self.screen.bind(&ctx); - ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 1.0)); + ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 0.0)); ctx.clear(); self.shader_upscale.bind(&ctx); self.render_framebuffer.bind_texture(&ctx); -- cgit v1.2.3