From 6c00c069ccf08ef5e577c16acc78a5b1f53a0f8f Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Sat, 18 Jan 2025 20:46:08 -0500 Subject: Rework font rendering, configurable resolution --- src/assets/shaders/bitmap/frag.glsl | 46 +---------- src/assets/shaders/bitmap/vert.glsl | 24 ++---- src/audio.rs | 5 +- src/context.rs | 39 +++++----- src/font.rs | 149 ++++++++++++++++++++++++------------ src/framebuffer.rs | 6 +- src/lib.rs | 19 +++-- src/net/client.rs | 69 +---------------- src/net/client/wasm.rs | 67 ++++++++++++++++ src/shader.rs | 4 +- src/state.rs | 21 ++--- src/utils.rs | 4 +- 12 files changed, 230 insertions(+), 223 deletions(-) create mode 100644 src/net/client/wasm.rs (limited to 'src') diff --git a/src/assets/shaders/bitmap/frag.glsl b/src/assets/shaders/bitmap/frag.glsl index 94d27c9..470a7b8 100644 --- a/src/assets/shaders/bitmap/frag.glsl +++ b/src/assets/shaders/bitmap/frag.glsl @@ -2,55 +2,13 @@ precision highp float; uniform sampler2D texture_data; -uniform int text_length; -uniform int text[256]; -uniform int char_width; -uniform int char_height; -uniform int font_width; -uniform int font_height; -uniform int text_width; -uniform int text_height; uniform vec3 text_color; in vec2 vertex_texcoord; out vec4 frag_color; -void main() -{ - vec2 inverted_texcoord = vec2(vertex_texcoord.x, 1.0 - vertex_texcoord.y); - vec2 texcoord_pixels = inverted_texcoord * vec2(float(text_width), float(text_height)); - int texcoord_char_x = int(floor(texcoord_pixels.x)) / char_width; - int texcoord_char_y = int(floor(texcoord_pixels.y)) / char_height; - - int x = 0; - int y = 0; - int i = 0; - for (; i < text_length; ++i) { - if (x == texcoord_char_x && y == texcoord_char_y) { - break; - } - if (text[i] == 10) { - x = 0; - y += 1; - } else { - x += 1; - } - } - if (i == text_length || text[i] == 10) discard; - - int entry = text[i] - 32; - vec2 texcoord_base = vec2( - float(entry % (font_width / char_width)) * float(char_width), - float(entry / (font_width / char_width)) * float(char_height) - ); - // vec2 texcoord_base = vec2(8.0, 0.0); - vec2 texcoord_off = vec2( - mod(texcoord_pixels.x, float(char_width)), - mod(texcoord_pixels.y, float(char_height)) - ); - vec2 texcoord_final = (texcoord_base + texcoord_off) / vec2(float(font_width), float(font_height)); - - vec4 texel = texture(texture_data, texcoord_final); +void main() { + vec4 texel = texture(texture_data, vertex_texcoord); if (texel.rgb == vec3(0.0, 0.0, 0.0)) discard; texel.r = text_color.r; texel.g = text_color.g; diff --git a/src/assets/shaders/bitmap/vert.glsl b/src/assets/shaders/bitmap/vert.glsl index 4005d75..4ff9865 100644 --- a/src/assets/shaders/bitmap/vert.glsl +++ b/src/assets/shaders/bitmap/vert.glsl @@ -1,26 +1,14 @@ #version 300 es precision highp float; -uniform mat4 view; -uniform mat4 position; +in vec2 vertex; +in vec2 texcoord; + +uniform mat4 transform; out vec2 vertex_texcoord; void main() { - const vec2 positions[4] = vec2[]( - vec2(-1, -1), - vec2(+1, -1), - vec2(-1, +1), - vec2(+1, +1) - ); - const vec2 coords[4] = vec2[]( - vec2(0, 0), - vec2(1, 0), - vec2(0, 1), - vec2(1, 1) - ); - vec4 vertex = vec4(positions[gl_VertexID], 0.0, 1.0); - - vertex_texcoord = coords[gl_VertexID]; - gl_Position = view * position * vertex; + vertex_texcoord = texcoord; + gl_Position = transform * vec4(vertex, 0.0, 1.0); } diff --git a/src/audio.rs b/src/audio.rs index 0dca32e..2b4226c 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -1,4 +1,7 @@ -use std::{cell::RefCell, collections::HashMap}; +use std::collections::HashMap; + +#[cfg(target_arch = "wasm32")] +use std::cell::RefCell; #[cfg(target_arch = "wasm32")] pub struct Context { diff --git a/src/context.rs b/src/context.rs index 28d0a79..ca3ebe3 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,24 +10,10 @@ extern { fn js_poll_resized() -> bool; } -pub const RENDER_WIDTH: f32 = 240.0; -pub const RENDER_HEIGHT: f32 = 160.0; - -pub fn compute_upscale(windoww: u32, windowh: u32) -> u32 { - let mut ratio = 1; - loop { - if (RENDER_WIDTH as u32) * ratio > windoww - || (RENDER_HEIGHT as u32) * ratio > windowh - { - break; - } - ratio += 1; - } - (ratio - 1).max(1) -} - #[cfg(not(target_arch = "wasm32"))] pub struct Context { + pub render_width: f32, + pub render_height: f32, pub window: sdl2::video::Window, pub gl: glow::Context, pub emptyvao: glow::VertexArray, @@ -37,6 +23,8 @@ pub struct Context { #[cfg(target_arch = "wasm32")] pub struct Context { + pub render_width: f32, + pub render_height: f32, pub window: winit::window::Window, pub gl: glow::Context, pub emptyvao: glow::VertexArray, @@ -44,12 +32,26 @@ pub struct Context { } impl Context { + pub fn compute_upscale(&self, windoww: u32, windowh: u32) -> u32 { + let mut ratio = 1; + loop { + if (self.render_width as u32) * ratio > windoww + || (self.render_height as u32) * ratio > windowh + { + break; + } + ratio += 1; + } + (ratio - 1).max(1) + } + #[cfg(not(target_arch = "wasm32"))] - pub fn new(sdl: sdl2::Sdl, window: sdl2::video::Window, gl: glow::Context) -> Self { + pub fn new(sdl: sdl2::Sdl, window: sdl2::video::Window, 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, gl, emptyvao, @@ -60,7 +62,7 @@ impl Context { } #[cfg(target_arch = "wasm32")] - pub fn new(window: winit::window::Window, gl: glow::Context) -> Self { + pub fn new(window: winit::window::Window, gl: glow::Context, render_width: f32, render_height: f32) -> Self { let emptyvao = unsafe { gl.create_vertex_array().expect("failed to initialize vao") }; @@ -69,6 +71,7 @@ impl Context { unsafe { js_track_resized_setup(); } let ret = Self { + render_width, render_height, window, gl, emptyvao, diff --git a/src/font.rs b/src/font.rs index fb8f133..047e1f7 100644 --- a/src/font.rs +++ b/src/font.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::{context, texture, shader}; +use crate::{context, mesh, shader, texture}; use glow::HasContext; pub const CHAR_WIDTH: i32 = 7; @@ -11,6 +11,10 @@ pub const FONT_HEIGHT: i32 = 54; pub struct Bitmap { pub shader: shader::Shader, pub font: texture::Texture, + pub vao: glow::VertexArray, + pub vertex_buf: glow::Buffer, + pub texcoords_buf: glow::Buffer, + pub index_buf: glow::Buffer, } impl Bitmap { @@ -21,67 +25,110 @@ impl Bitmap { include_str!("assets/shaders/bitmap/frag.glsl"), ); let font = texture::Texture::new(ctx, include_bytes!("assets/fonts/simple.png")); - Self { - shader, - font, + unsafe { + let vao = ctx.gl.create_vertex_array().expect("failed to initialize vao"); + ctx.gl.bind_vertex_array(Some(vao)); + + let vertex_buf = ctx.gl.create_buffer().expect("failed to create buffer object"); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buf)); + ctx.gl.vertex_attrib_pointer_f32(mesh::ATTRIB_VERTEX, 2, glow::FLOAT, false, 0, 0); + ctx.gl.enable_vertex_attrib_array(mesh::ATTRIB_VERTEX); + + let texcoords_buf = ctx.gl.create_buffer().expect("failed to create buffer object"); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(texcoords_buf)); + ctx.gl.vertex_attrib_pointer_f32(mesh::ATTRIB_TEXCOORD, 2, glow::FLOAT, false, 0, 0); + ctx.gl.enable_vertex_attrib_array(mesh::ATTRIB_TEXCOORD); + + let index_buf = ctx.gl.create_buffer().expect("failed to create buffer object"); + ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(index_buf)); + Self { + shader, + font, + vao, + vertex_buf, + texcoords_buf, + index_buf, + } } } pub fn render_text_helper(&self, ctx: &context::Context, pos: &glam::Vec2, text: &str, color: &glam::Vec3) { - let mut width = 0; - let mut linewidth = 0; - let mut height = CHAR_HEIGHT; + let mut cur = glam::Vec2::new(0.0, 0.0); + let mut vertices = Vec::new(); + let mut texcoords = Vec::new(); + let mut indices = Vec::new(); + let cwidth = CHAR_WIDTH as f32 / FONT_WIDTH as f32; + let cheight = CHAR_HEIGHT as f32 / FONT_HEIGHT as f32; + let row_len = FONT_WIDTH as u32 / CHAR_WIDTH as u32; for c in text.chars() { if c == '\n' { - width = width.max(linewidth); - linewidth = 0; - height += CHAR_HEIGHT; + cur.x = 0.0; + cur.y += CHAR_HEIGHT as f32; } else { - linewidth += CHAR_WIDTH; + let idx = vertices.len() as u32; + vertices.push(cur); + vertices.push(cur + glam::Vec2::new(CHAR_WIDTH as f32, 0.0)); + vertices.push(cur + glam::Vec2::new(CHAR_WIDTH as f32, CHAR_HEIGHT as f32)); + vertices.push(cur + glam::Vec2::new(0.0, CHAR_HEIGHT as f32)); + let cidx = c as u32 - ' ' as u32; + let col = cidx % row_len; + let row = cidx / row_len; + let tcbase = glam::Vec2::new(col as f32 * cwidth, row as f32 * cheight); + texcoords.push(tcbase + glam::Vec2::new(0.0, cheight)); + texcoords.push(tcbase + glam::Vec2::new(cwidth, cheight)); + texcoords.push(tcbase + glam::Vec2::new(cwidth, 0.0)); + texcoords.push(tcbase); + indices.push(idx + 0); indices.push(idx + 1); indices.push(idx + 2); + indices.push(idx + 0); indices.push(idx + 3); indices.push(idx + 2); + cur.x += CHAR_WIDTH as f32; } } - width = width.max(linewidth); - + let index_bytes: Vec = indices.iter().flat_map(|x| x.to_ne_bytes()).collect(); self.shader.bind(ctx); - let len = text.len().min(256); - self.shader.set_i32(ctx, "text_length", len as _); - let textvals: Vec = text.as_bytes().into_iter().take(len).map(|b| { - *b as i32 - }).collect(); - self.shader.set_i32_array(ctx, "text[0]", &textvals); - self.shader.set_i32(ctx, "char_width", CHAR_WIDTH as _); - self.shader.set_i32(ctx, "char_height", CHAR_HEIGHT as _); - self.shader.set_i32(ctx, "font_width", FONT_WIDTH as _); - self.shader.set_i32(ctx, "font_height", FONT_HEIGHT as _); - self.shader.set_i32(ctx, "text_width", width as _); - self.shader.set_i32(ctx, "text_height", height as _); - self.shader.set_vec3(ctx, "text_color", color as _); - self.shader.set_mat4( - ctx, "view", - &glam::Mat4::from_scale( - glam::Vec3::new( - 2.0 / context::RENDER_WIDTH, - 2.0 / context::RENDER_HEIGHT, - 1.0, - ), - ), + self.font.bind(ctx); + let scale = glam::Vec2::new(2.0 / ctx.render_width, 2.0 / ctx.render_height); + let offset = glam::Vec2::new( + -ctx.render_width / 2.0, + ctx.render_height / 2.0 - CHAR_HEIGHT as f32, ); - let halfwidth = width as f32 / 2.0; - let halfheight = height as f32 / 2.0; + let npos = (glam::Vec2::new(pos.x, -pos.y) + offset) * scale; + self.shader.set_vec3(ctx, "text_color", color as _); self.shader.set_mat4( - ctx, "position", + ctx, "transform", &glam::Mat4::from_scale_rotation_translation( - glam::Vec3::new(halfwidth, halfheight, 1.0), + glam::Vec3::new(scale.x, scale.y, 1.0), glam::Quat::IDENTITY, - glam::Vec3::new( - -context::RENDER_WIDTH / 2.0 + pos.x + halfwidth, - context::RENDER_HEIGHT / 2.0 - pos.y - halfheight, - 0.0, - ), - ) + glam::Vec3::new(npos.x, npos.y, 0.0), + ), ); - self.font.bind(ctx); - ctx.render_no_geometry(); + unsafe { + ctx.gl.bind_vertex_array(Some(self.vao)); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vertex_buf)); + ctx.gl.buffer_data_u8_slice( + glow::ARRAY_BUFFER, + std::slice::from_raw_parts( + vertices.as_ptr() as _, + vertices.len() * std::mem::size_of::() * 2, + ), + glow::STATIC_DRAW, + ); + ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.texcoords_buf)); + ctx.gl.buffer_data_u8_slice( + glow::ARRAY_BUFFER, + std::slice::from_raw_parts( + texcoords.as_ptr() as _, + texcoords.len() * std::mem::size_of::() * 2, + ), + glow::STATIC_DRAW, + ); + ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.index_buf)); + ctx.gl.buffer_data_u8_slice( + glow::ELEMENT_ARRAY_BUFFER, + &index_bytes, + glow::STATIC_DRAW, + ); + ctx.gl.draw_elements(glow::TRIANGLES, indices.len() as _, glow::UNSIGNED_INT, 0); + } } pub fn render_text(&self, ctx: &context::Context, pos: &glam::Vec2, text: &str) { @@ -180,8 +227,8 @@ impl TrueType { ctx, "view", &glam::Mat4::from_scale( glam::Vec3::new( - 2.0 / context::RENDER_WIDTH, - 2.0 / context::RENDER_HEIGHT, + 2.0 / ctx.render_width, + 2.0 / ctx.render_height, 1.0, ), ), @@ -193,8 +240,8 @@ impl TrueType { glam::Vec3::new(width as f32 / 2.0, self.cellheight as f32 / 2.0, 1.0), glam::Quat::IDENTITY, glam::Vec3::new( - -context::RENDER_WIDTH / 2.0 + pos.x + width as f32 / 2.0, - context::RENDER_HEIGHT / 2.0 - pos.y - self.cellheight as f32 / 2.0, + -ctx.render_width / 2.0 + pos.x + width as f32 / 2.0, + ctx.render_height / 2.0 - pos.y - self.cellheight as f32 / 2.0, 0.0, ), ) diff --git a/src/framebuffer.rs b/src/framebuffer.rs index 6d8d1b5..ae96d6a 100644 --- a/src/framebuffer.rs +++ b/src/framebuffer.rs @@ -18,9 +18,9 @@ impl Framebuffer { let (w, h) = ctx.window.size(); (w as f32, h as f32) }; - let ratio = context::compute_upscale(windoww as _, windowh as _) as f32; - let upscalew = context::RENDER_WIDTH * ratio; - let upscaleh = context::RENDER_HEIGHT * ratio; + let ratio = ctx.compute_upscale(windoww as _, windowh as _) as f32; + let upscalew = ctx.render_width * ratio; + let upscaleh = ctx.render_height * ratio; let offsetx = (windoww - upscalew) / 2.0; let offsety = (windowh - upscaleh) / 2.0; Self { diff --git a/src/lib.rs b/src/lib.rs index f50bb09..32502d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,8 @@ pub mod font; pub mod shadow; pub mod audio; pub mod net; + +#[cfg(target_arch = "wasm32")] use std::ops::Rem; #[cfg(target_arch = "wasm32")] @@ -39,7 +41,7 @@ where } #[cfg(not(target_arch = "wasm32"))] -pub async fn run<'a, F, G, Fut>(title: &str, gnew: F) +pub async fn run<'a, F, G, Fut>(title: &str, w: u32, h: u32, gnew: F) where Fut: std::future::Future, G: state::Game + 'static, @@ -72,7 +74,7 @@ where (sdl, window, gl, event_loop, gl_context) }; - let ctx = Box::leak(Box::new(context::Context::new(sdl, window, gl))); + let ctx = Box::leak(Box::new(context::Context::new(sdl, 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))); @@ -140,7 +142,7 @@ where } #[cfg(target_arch = "wasm32")] -pub async fn run<'a, F, G, Fut>(gnew: F) +pub async fn run<'a, F, G, Fut>(w: u32, h: u32, gnew: F) where Fut: std::future::Future, G: state::Game + 'static, @@ -176,7 +178,7 @@ where (window, gl) }; - let ctx = Box::leak(Box::new(context::Context::new(window, gl))); + let ctx = Box::leak(Box::new(context::Context::new(window, gl, w as f32, h as f32))); ctx.maximize_canvas(); let game = Box::leak(Box::new(gnew(ctx).await)); let st = Box::leak(Box::new(state::State::new(&ctx))); @@ -271,7 +273,6 @@ where #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; - #[cfg(target_arch = "wasm32")] struct TestGame { font: font::Bitmap, @@ -281,6 +282,7 @@ struct TestGame { tex: texture::Texture, shader: shader::Shader, } +#[cfg(target_arch = "wasm32")] impl TestGame { pub async fn new(ctx: &context::Context) -> Self { Self { @@ -293,6 +295,7 @@ impl TestGame { } } } +#[cfg(target_arch = "wasm32")] impl state::Game for TestGame { fn update(&mut self, ctx: &context::Context, st: &mut state::State) -> Option<()> { st.move_camera( @@ -319,8 +322,8 @@ impl state::Game for TestGame { ); self.tex.bind(ctx); self.fox.render(ctx, &self.shader); - self.font.render_text(ctx, &glam::Vec2::new(0.0, 0.0), "he's all FIXED up"); - self.tt.render_text(ctx, &glam::Vec2::new(10.0, 10.0), "tESTge"); + self.font.render_text(ctx, &glam::Vec2::new(0.0, 10.0), "he's all FIXED up"); + // self.tt.render_text(ctx, &glam::Vec2::new(10.0, 10.0), "tESTge"); Some(()) } } @@ -328,5 +331,5 @@ impl state::Game for TestGame { #[cfg(target_arch = "wasm32")] #[wasm_bindgen] pub async fn main_js_test() { - run(TestGame::new).await; + run(240, 160, TestGame::new).await; } diff --git a/src/net/client.rs b/src/net/client.rs index d9936e5..fcd51b8 100644 --- a/src/net/client.rs +++ b/src/net/client.rs @@ -1,67 +1,2 @@ -use std::{collections::VecDeque, sync::{Arc, Mutex}}; - -use wasm_bindgen::prelude::*; - -#[derive(Debug)] -pub enum Message { - Binary(Vec), - Text(String), -} - -impl Message { - pub fn from_messageevent(e: web_sys::MessageEvent) -> Self { - if let Ok(abuf) = e.data().dyn_into::() { - let array = js_sys::Uint8Array::new(&abuf).to_vec(); - Message::Binary(array) - } else if let Ok(txt) = e.data().dyn_into::() { - Message::Text(txt.into()) - } else { - panic!("received weird websocked message: {:?}", e); - } - } -} - -pub struct Client { - pub ws: Option, - pub messages: Arc>>, -} - -impl Client { - pub fn new() -> Self { - Self { - ws: None, - messages: Arc::new(Mutex::new(VecDeque::new())), - } - } - pub fn connect(&mut self, url: &str) { - let ws = web_sys::WebSocket::new(url).expect("failed to open websocket"); - let messages_ref = self.messages.clone(); - let cb: Closure = Closure::new(move |e: web_sys::MessageEvent| { - let msg = Message::from_messageevent(e); - log::info!("incoming: {:?}", msg); - messages_ref.lock().unwrap().push_back(msg); - }); - ws.set_onmessage(Some(cb.as_ref().unchecked_ref())); - cb.forget(); - self.ws = Some(ws); - } - pub fn poll(&mut self) -> Option { - self.messages.lock().unwrap().pop_front() - } - pub fn send(&self, msg: Message) { - if let Some(ws) = &self.ws { - match msg { - Message::Text(txt) => { - if let Err(e) = ws.send_with_str(&txt) { - log::warn!("failed to send string: {:?}", e); - } - }, - Message::Binary(bytes) => { - if let Err(e) = ws.send_with_u8_array(&bytes) { - log::warn!("failed to send bytes: {:?}", e); - } - }, - } - } - } -} +#[cfg(target_arch = "wasm32")] +pub mod wasm; diff --git a/src/net/client/wasm.rs b/src/net/client/wasm.rs new file mode 100644 index 0000000..d9936e5 --- /dev/null +++ b/src/net/client/wasm.rs @@ -0,0 +1,67 @@ +use std::{collections::VecDeque, sync::{Arc, Mutex}}; + +use wasm_bindgen::prelude::*; + +#[derive(Debug)] +pub enum Message { + Binary(Vec), + Text(String), +} + +impl Message { + pub fn from_messageevent(e: web_sys::MessageEvent) -> Self { + if let Ok(abuf) = e.data().dyn_into::() { + let array = js_sys::Uint8Array::new(&abuf).to_vec(); + Message::Binary(array) + } else if let Ok(txt) = e.data().dyn_into::() { + Message::Text(txt.into()) + } else { + panic!("received weird websocked message: {:?}", e); + } + } +} + +pub struct Client { + pub ws: Option, + pub messages: Arc>>, +} + +impl Client { + pub fn new() -> Self { + Self { + ws: None, + messages: Arc::new(Mutex::new(VecDeque::new())), + } + } + pub fn connect(&mut self, url: &str) { + let ws = web_sys::WebSocket::new(url).expect("failed to open websocket"); + let messages_ref = self.messages.clone(); + let cb: Closure = Closure::new(move |e: web_sys::MessageEvent| { + let msg = Message::from_messageevent(e); + log::info!("incoming: {:?}", msg); + messages_ref.lock().unwrap().push_back(msg); + }); + ws.set_onmessage(Some(cb.as_ref().unchecked_ref())); + cb.forget(); + self.ws = Some(ws); + } + pub fn poll(&mut self) -> Option { + self.messages.lock().unwrap().pop_front() + } + pub fn send(&self, msg: Message) { + if let Some(ws) = &self.ws { + match msg { + Message::Text(txt) => { + if let Err(e) = ws.send_with_str(&txt) { + log::warn!("failed to send string: {:?}", e); + } + }, + Message::Binary(bytes) => { + if let Err(e) = ws.send_with_u8_array(&bytes) { + log::warn!("failed to send bytes: {:?}", e); + } + }, + } + } + } +} diff --git a/src/shader.rs b/src/shader.rs index 46deb82..cbaf3ee 100644 --- a/src/shader.rs +++ b/src/shader.rs @@ -210,8 +210,8 @@ impl Shader { glam::Vec3::new(halfwidth, halfheight, 1.0), rot.clone(), glam::Vec3::new( - -context::RENDER_WIDTH / 2.0 + pos.x + halfwidth, - context::RENDER_HEIGHT / 2.0 - pos.y - halfheight, + -ctx.render_width / 2.0 + pos.x + halfwidth, + ctx.render_height / 2.0 - pos.y - halfheight, 0.0, ), ) diff --git a/src/state.rs b/src/state.rs index 0be163b..cf910a3 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use bimap::BiHashMap; use enum_map::{enum_map, Enum, EnumMap}; +use serde::{Serialize, Deserialize}; use crate::{context, framebuffer, shader, audio}; @@ -35,7 +36,7 @@ pub trait Game { fn render(&mut self, ctx: &context::Context, st: &mut State) -> Option<()> { Some(()) } } -#[derive(Debug, Enum, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Enum, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Key { Up, Down, Left, Right, A, B, L, R, @@ -96,10 +97,10 @@ pub struct PointLight { type Timestamp = f64; #[cfg(target_arch = "wasm32")] -type Keycode = winit::keyboard::KeyCode; +pub type Keycode = winit::keyboard::KeyCode; #[cfg(not(target_arch = "wasm32"))] -type Keycode = sdl2::keyboard::Keycode; +pub type Keycode = sdl2::keyboard::Keycode; pub struct State { pub acc: f64, @@ -175,7 +176,7 @@ impl State { let screen = framebuffer::Framebuffer::screen(ctx); let render_framebuffer = framebuffer::Framebuffer::new( ctx, - &glam::Vec2::new(context::RENDER_WIDTH, context::RENDER_HEIGHT), + &glam::Vec2::new(ctx.render_width, ctx.render_height), &glam::Vec2::new(0.0, 0.0), ); let shader_upscale = shader::Shader::new_nolib( @@ -209,7 +210,7 @@ impl State { projection: glam::Mat4::perspective_lh( std::f32::consts::PI / 4.0, - context::RENDER_WIDTH / context::RENDER_HEIGHT, + ctx.render_width / ctx.render_height, // 0.1, 0.5, 50.0, @@ -342,8 +343,8 @@ impl State { ctx, "view", &glam::Mat4::from_scale( glam::Vec3::new( - 2.0 / context::RENDER_WIDTH, - 2.0 / context::RENDER_HEIGHT, + 2.0 / ctx.render_width, + 2.0 / ctx.render_height, 1.0, ), ), @@ -357,9 +358,9 @@ impl State { game: &mut G ) where G: Game { - let rx = ((x - self.screen.offsets.x) * context::RENDER_WIDTH / self.screen.dims.x) as i32; - let ry = ((y - self.screen.offsets.y) * context::RENDER_HEIGHT / self.screen.dims.y) as i32; - if !(rx < 0 || rx >= context::RENDER_WIDTH as i32 || ry < 0 || ry >= context::RENDER_HEIGHT as i32) { + 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); } } diff --git a/src/utils.rs b/src/utils.rs index af0d77d..4d5916c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,6 @@ -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +use serde::{Serialize, Deserialize}; + +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub enum Cardinal { North, South, -- cgit v1.2.3