From 5bc3f17670c8979e65eaac67787b55dfef2e87c1 Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Wed, 29 Apr 2026 20:33:53 -0400 Subject: Add width and height to textures --- crates/teleia/Cargo.toml | 2 +- crates/teleia/src/context.rs | 12 ++++++++++++ crates/teleia/src/lib.rs | 17 +++++++++-------- crates/teleia/src/scene.rs | 2 +- crates/teleia/src/state.rs | 31 ++++++++++++++++++++----------- crates/teleia/src/texture.rs | 28 +++++++++++++++++++++++++++- 6 files changed, 70 insertions(+), 22 deletions(-) (limited to 'crates') diff --git a/crates/teleia/Cargo.toml b/crates/teleia/Cargo.toml index 05ec74a..1704309 100644 --- a/crates/teleia/Cargo.toml +++ b/crates/teleia/Cargo.toml @@ -46,7 +46,7 @@ web-sys = { version = "*", features = ["Document", "Window", "Element", "HtmlCan [target.'cfg(not(target_arch = "wasm32"))'.dependencies] env_logger = "0.11.5" # configurable logging to stdout glfw = { git = "https://github.com/lcolonq/glfw-rs", features = ["serde"] } # window management -kira = { version = "=0.9.6", default-features = false, features = ["cpal", "ogg", "wav"] } # audio +kira = { version = "=0.9.6", default-features = false, features = ["cpal", "ogg", "mp3", "wav"] } # audio directories = { git = "https://github.com/lcolonq/directories-rs" } # standard system directories polling = "3.11.0" # interface to epoll tungstenite = { version = "0.24.0", features = ["native-tls"] } # websockets \ No newline at end of file diff --git a/crates/teleia/src/context.rs b/crates/teleia/src/context.rs index 8547d59..6346237 100644 --- a/crates/teleia/src/context.rs +++ b/crates/teleia/src/context.rs @@ -1,6 +1,7 @@ use crate::Options; use glow::HasContext; +use glfw::Context as _; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; @@ -257,6 +258,17 @@ impl Context { } } + #[cfg(not(target_arch = "wasm32"))] + pub fn lock_mouse(&self) { + unsafe { + glfw::ffi::glfwSetInputMode( + self.window.borrow_mut().window_ptr(), + glfw::ffi::CURSOR, + glfw::ffi::CURSOR_DISABLED, + ); + } + } + pub fn check_error(&self) { unsafe { let err = self.gl.get_error(); diff --git a/crates/teleia/src/lib.rs b/crates/teleia/src/lib.rs index 85a5f4e..21f3b24 100644 --- a/crates/teleia/src/lib.rs +++ b/crates/teleia/src/lib.rs @@ -38,10 +38,11 @@ use glfw::Context; use bitflags::bitflags; bitflags! { pub struct Options: u32 { - const OVERLAY = 0b00000001; - const HIDDEN = 0b00000010; - const NORESIZE = 0b00000100; - const EGL = 0b00001000; + const OVERLAY = 0b00000001; + const HIDDEN = 0b00000010; + const NORESIZE = 0b00000100; + const EGL = 0b00001000; + const FULLSCREEN_MOUSE = 0b00010000; } } @@ -161,10 +162,10 @@ where st.keys = state::Keys::new(); }, glfw::WindowEvent::CursorPos(x, y) => { - st.mouse_moved(&ctx, x as f32, y as f32, game); + st.mouse_moved(&ctx, x as f32, y as f32, game)?; } glfw::WindowEvent::MouseButton(_, glfw::Action::Press, _) => { - st.mouse_pressed(&ctx, game) + st.mouse_pressed(&ctx, game)?; }, glfw::WindowEvent::MouseButton(_, glfw::Action::Release, _) => { st.mouse_released(&ctx) @@ -272,14 +273,14 @@ where st.keys = state::Keys::new(); }, winit::event::WindowEvent::CursorMoved { position, ..} => { - st.mouse_moved(&ctx, position.x as f32, position.y as f32, game); + st.mouse_moved(&ctx, position.x as f32, position.y as f32, game)?; }, winit::event::WindowEvent::MouseInput { state, .. } => match state { winit::event::ElementState::Pressed => { - st.mouse_pressed(&ctx, game) + st.mouse_pressed(&ctx, game)?; }, winit::event::ElementState::Released => { st.mouse_released(&ctx) diff --git a/crates/teleia/src/scene.rs b/crates/teleia/src/scene.rs index ccef8f6..6c9ab9a 100644 --- a/crates/teleia/src/scene.rs +++ b/crates/teleia/src/scene.rs @@ -233,7 +233,7 @@ impl Scene { Some(&i.as_bytes()), ); ctx.gl.generate_mipmap(glow::TEXTURE_2D); - texture::Texture { tex } + texture::Texture { tex, width: i.width() as i32, height: i.height() as i32 } } }).collect(); let materials: Vec = gltf.materials().map(|m| { diff --git a/crates/teleia/src/state.rs b/crates/teleia/src/state.rs index 8f4462a..2e50fbf 100644 --- a/crates/teleia/src/state.rs +++ b/crates/teleia/src/state.rs @@ -22,9 +22,9 @@ pub trait Game { ) -> HashMap { HashMap::new() } - fn finish_title(&mut self, st: &mut State) {} - fn mouse_move(&mut self, ctx: &context::Context, st: &mut State, x: i32, y: i32) {} - fn mouse_press(&mut self, ctx: &context::Context, st: &mut State) {} + fn finish_title(&mut self, ctx: &context::Context, st: &mut State) -> utils::Erm<()> { Ok(()) } + fn mouse_move(&mut self, ctx: &context::Context, st: &mut State, x: i32, y: i32) -> utils::Erm<()> { Ok(()) } + fn mouse_press(&mut self, ctx: &context::Context, st: &mut State) -> utils::Erm<()> { Ok(()) } fn update(&mut self, ctx: &context::Context, st: &mut State) -> utils::Erm<()> { Ok(()) } fn render(&mut self, ctx: &context::Context, st: &mut State) -> utils::Erm<()> { Ok(()) } } @@ -451,28 +451,37 @@ impl State { ctx: &context::Context, x: f32, y: f32, game: &mut G - ) where G: Game + ) -> utils::Erm<()> where G: Game { - let rx = ((x - self.screen.offsets.x) * ctx.render_width / self.screen.dims.x) as i32; - let ry = ((y - self.screen.offsets.y) * ctx.render_height / self.screen.dims.y) as i32; - if !(rx < 0 || rx >= ctx.render_width as i32 || ry < 0 || ry >= ctx.render_height as i32) { - game.mouse_move(ctx, self, rx, ry); + if ctx.options.contains(crate::Options::FULLSCREEN_MOUSE) { + game.mouse_move(ctx, self, + (x * ctx.render_width / self.screen.dims.x) as i32, + (y * ctx.render_height / self.screen.dims.y) as i32, + )?; + } else { + let rx = ((x - self.screen.offsets.x) * ctx.render_width / self.screen.dims.x) as i32; + let ry = ((y - self.screen.offsets.y) * ctx.render_height / self.screen.dims.y) as i32; + if !(rx < 0 || rx >= ctx.render_width as i32 || ry < 0 || ry >= ctx.render_height as i32) { + game.mouse_move(ctx, self, rx, ry)?; + } } + Ok(()) } pub fn mouse_pressed( &mut self, ctx: &context::Context, game: &mut G - ) where G: Game { + ) -> utils::Erm<()> where G: Game { log::info!("click"); if self.audio.is_none() { self.audio = Some(audio::Assets::new(|actx| { game.initialize_audio(ctx, &self, actx) })); - game.finish_title(self); + game.finish_title(ctx, self)?; } - game.mouse_press(ctx, self); + game.mouse_press(ctx, self)?; + Ok(()) } pub fn mouse_released( diff --git a/crates/teleia/src/texture.rs b/crates/teleia/src/texture.rs index f993c08..727eec2 100644 --- a/crates/teleia/src/texture.rs +++ b/crates/teleia/src/texture.rs @@ -5,6 +5,8 @@ use crate::context; pub struct Texture { pub tex: glow::Texture, + pub width: i32, + pub height: i32, } impl Texture { @@ -18,6 +20,7 @@ impl Texture { ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32); Self { tex, + width: 0, height: 0, } } } @@ -52,11 +55,24 @@ impl Texture { Self { tex, + width: rgba.width() as i32, + height: rgba.height() as i32, } } } - pub fn upload_rgba8(&self, ctx: &context::Context, width: i32, height: i32, data: &[u8]) { + pub fn upload(&mut self, ctx: &context::Context, bytes: &[u8]) { + let rgba = image::ImageReader::new(std::io::Cursor::new(bytes)) + .with_guessed_format() + .expect("failed to guess image format") + .decode() + .expect("failed to decode image") + .into_rgba8(); + let pixels = rgba.as_bytes(); + self.upload_rgba8(ctx, rgba.width() as i32, rgba.height() as i32, &pixels); + } + + pub fn upload_rgba8(&mut self, ctx: &context::Context, width: i32, height: i32, data: &[u8]) { unsafe { ctx.gl.bind_texture(glow::TEXTURE_2D, Some(self.tex)); ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::CLAMP_TO_EDGE as i32); @@ -76,6 +92,16 @@ impl Texture { ); ctx.gl.generate_mipmap(glow::TEXTURE_2D); } + self.width = width; + self.height = height; + } + + pub fn set_repeat(&self, ctx: &context::Context) { + unsafe { + ctx.gl.bind_texture(glow::TEXTURE_2D, Some(self.tex)); + ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32); + ctx.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::REPEAT as i32); + } } pub fn set_anisotropic_filtering(&self, ctx: &context::Context) { -- cgit v1.2.3