diff options
| author | LLLL Colonq <llll@colonq> | 2025-11-13 22:04:56 -0500 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2025-11-13 22:04:56 -0500 |
| commit | a76f583c2d11043a94c3251ec6a5381d7836bdb4 (patch) | |
| tree | bcb6a085fa5114be1354efa79cc6e191095f8253 /crates/renderer/src | |
| parent | e8bf4d7dde7d4f450458deb0612eb3bc14994901 (diff) | |
Add TCG
Diffstat (limited to 'crates/renderer/src')
| -rw-r--r-- | crates/renderer/src/assets.rs | 24 | ||||
| -rw-r--r-- | crates/renderer/src/assets/shaders/flat/frag.glsl | 3 | ||||
| -rw-r--r-- | crates/renderer/src/assets/shaders/tcg_base/frag.glsl | 60 | ||||
| -rw-r--r-- | crates/renderer/src/assets/shaders/tcg_base/vert.glsl | 4 | ||||
| -rw-r--r-- | crates/renderer/src/assets/shaders/tcg_screen/frag.glsl | 7 | ||||
| -rw-r--r-- | crates/renderer/src/assets/textures/tcg/factions/lever.png | bin | 0 -> 366 bytes | |||
| -rw-r--r-- | crates/renderer/src/assets/textures/tcg/factions/nate.png | bin | 0 -> 323 bytes | |||
| -rw-r--r-- | crates/renderer/src/assets/textures/tcg/factions/tony.png | bin | 0 -> 272 bytes | |||
| -rw-r--r-- | crates/renderer/src/overlay.rs | 16 | ||||
| -rw-r--r-- | crates/renderer/src/overlay/tcg.rs | 325 |
10 files changed, 359 insertions, 80 deletions
diff --git a/crates/renderer/src/assets.rs b/crates/renderer/src/assets.rs index 83b5a0d..1006c13 100644 --- a/crates/renderer/src/assets.rs +++ b/crates/renderer/src/assets.rs @@ -4,6 +4,10 @@ pub struct Assets { pub font: font::Bitmap, pub shader_flat: shader::Shader, pub shader_scene: shader::Shader, + pub shader_color: shader::Shader, + pub shader_tcg: shader::Shader, + pub shader_tcg_screen: shader::Shader, + pub shader_tcg_base: shader::Shader, pub texture_adblock: texture::Texture, pub texture_mod: texture::Texture, pub texture_operatop: texture::Texture, @@ -24,6 +28,26 @@ impl Assets { include_str!("assets/shaders/scene/vert.glsl"), include_str!("assets/shaders/scene/frag.glsl") ), + shader_color: shader::Shader::new( + ctx, + include_str!("assets/shaders/color/vert.glsl"), + include_str!("assets/shaders/color/frag.glsl") + ), + shader_tcg: shader::Shader::new( + ctx, + include_str!("assets/shaders/tcg/vert.glsl"), + include_str!("assets/shaders/tcg/frag.glsl") + ), + shader_tcg_screen: shader::Shader::new( + ctx, + include_str!("assets/shaders/tcg_screen/vert.glsl"), + include_str!("assets/shaders/tcg_screen/frag.glsl") + ), + shader_tcg_base: shader::Shader::new( + ctx, + include_str!("assets/shaders/tcg_base/vert.glsl"), + include_str!("assets/shaders/tcg_base/frag.glsl") + ), texture_adblock: texture::Texture::new(ctx, include_bytes!("assets/textures/adblock.png")), texture_mod: texture::Texture::new(ctx, include_bytes!("assets/textures/mod.png")), texture_operatop: texture::Texture::new(ctx, include_bytes!("assets/textures/operatop.png")), diff --git a/crates/renderer/src/assets/shaders/flat/frag.glsl b/crates/renderer/src/assets/shaders/flat/frag.glsl index cab840d..69fe2ec 100644 --- a/crates/renderer/src/assets/shaders/flat/frag.glsl +++ b/crates/renderer/src/assets/shaders/flat/frag.glsl @@ -7,9 +7,6 @@ void main() float opacity = 1.0 - clamp(transparency, 0.0, 1.0); vec2 tcfull = vec2(vertex_texcoord.x, 1.0 - vertex_texcoord.y); vec4 texel = texture(texture_data, tcfull); - if (texel.a != 1.0) { - discard; - } texel.a *= opacity; frag_color = texel; } diff --git a/crates/renderer/src/assets/shaders/tcg_base/frag.glsl b/crates/renderer/src/assets/shaders/tcg_base/frag.glsl new file mode 100644 index 0000000..b941d61 --- /dev/null +++ b/crates/renderer/src/assets/shaders/tcg_base/frag.glsl @@ -0,0 +1,60 @@ +uniform sampler2D texture_data; + +uniform vec4 shift_color; + +vec3 rgb_to_hsl(vec3 rgb) { + vec3 ret; + float min = min(min(rgb.r, rgb.g), rgb.b); + float max = max(max(rgb.r, rgb.g), rgb.b); + float lum = (max + min) / 2.0; + ret.z = lum; + if (max == min) { + ret.x = ret.y = 0.0; + } else { + float chroma = max - min; + ret.y = chroma / (1.0 - abs(2.0 * lum - 1.0)); + if (max == rgb.r) { + ret.x = (rgb.g - rgb.b) / chroma + (rgb.g < rgb.b ? 6.0 : 0.0); + } else if (max == rgb.g) { + ret.x = (rgb.b - rgb.r) / chroma + 2.0; + } else { + ret.x = (rgb.r - rgb.g) / chroma + 4.0; + } + ret.x /= 6.0; + } + return ret; +} + +float hue_to_rgb(float p, float q, float t) { + if (t < 0.0) t += 1.0; + if (t > 1.0) t -= 1.0; + if (t < 1.0/6.0) return p + (q - p) * 6.0 * t; + if (t < 1.0/2.0) return q; + if (t < 2.0/3.0) return p + (q - p) * (2.0/3.0 - t) * 6.0; + return p; +} + +vec3 hsl_to_rgb(vec3 hsl) { + vec3 ret; + if (hsl.y == 0.0) { + ret.r = ret.g = ret.b = hsl.z; + } else { + float q = hsl.z < 0.5 ? hsl.z * (1.0 + hsl.y) : hsl.z + hsl.y - hsl.z * hsl.y; + float p = 2.0 * hsl.z - q; + ret.r = hue_to_rgb(p, q, hsl.x + 1.0/3.0); + ret.g = hue_to_rgb(p, q, hsl.x); + ret.b = hue_to_rgb(p, q, hsl.x - 1.0/3.0); + } + return ret; +} + +void main() +{ + vec2 tcfull = vec2(vertex_texcoord.x, 1.0 - vertex_texcoord.y); + vec4 texel = texture(texture_data, tcfull); + vec3 hsl = rgb_to_hsl(texel.xyz); + vec3 shift_hsl = rgb_to_hsl(shift_color.xyz); + hsl.x = shift_hsl.x; + texel.xyz = hsl_to_rgb(hsl); + frag_color = texel; +} diff --git a/crates/renderer/src/assets/shaders/tcg_base/vert.glsl b/crates/renderer/src/assets/shaders/tcg_base/vert.glsl new file mode 100644 index 0000000..e324f7e --- /dev/null +++ b/crates/renderer/src/assets/shaders/tcg_base/vert.glsl @@ -0,0 +1,4 @@ +void main() +{ + default_main(); +}
\ No newline at end of file diff --git a/crates/renderer/src/assets/shaders/tcg_screen/frag.glsl b/crates/renderer/src/assets/shaders/tcg_screen/frag.glsl index 2a14860..cb4a58f 100644 --- a/crates/renderer/src/assets/shaders/tcg_screen/frag.glsl +++ b/crates/renderer/src/assets/shaders/tcg_screen/frag.glsl @@ -1,15 +1,12 @@ uniform sampler2D texture_data; -uniform float transparency; - void main() { - float opacity = 1.0 - clamp(transparency, 0.0, 1.0); vec2 tcfull = vec2(vertex_texcoord.x, vertex_texcoord.y); vec4 texel = texture(texture_data, tcfull); - if (texel.a != 1.0) { + if (texel.a == 0.0) { discard; } - texel.a *= opacity; + texel.a = 1.0; frag_color = texel; } diff --git a/crates/renderer/src/assets/textures/tcg/factions/lever.png b/crates/renderer/src/assets/textures/tcg/factions/lever.png Binary files differnew file mode 100644 index 0000000..a757baa --- /dev/null +++ b/crates/renderer/src/assets/textures/tcg/factions/lever.png diff --git a/crates/renderer/src/assets/textures/tcg/factions/nate.png b/crates/renderer/src/assets/textures/tcg/factions/nate.png Binary files differnew file mode 100644 index 0000000..38a45e5 --- /dev/null +++ b/crates/renderer/src/assets/textures/tcg/factions/nate.png diff --git a/crates/renderer/src/assets/textures/tcg/factions/tony.png b/crates/renderer/src/assets/textures/tcg/factions/tony.png Binary files differnew file mode 100644 index 0000000..c6ccaf0 --- /dev/null +++ b/crates/renderer/src/assets/textures/tcg/factions/tony.png diff --git a/crates/renderer/src/overlay.rs b/crates/renderer/src/overlay.rs index af02eda..049d788 100644 --- a/crates/renderer/src/overlay.rs +++ b/crates/renderer/src/overlay.rs @@ -44,6 +44,8 @@ pub struct Info { pub struct State { assets: assets::Assets, + redis: redis::Client, + redis_conn: redis::Connection, model: scene::Scene, model_neck_base: glam::Mat4, fig_binary: fig::BinaryClient, @@ -61,8 +63,11 @@ impl State { .and_then(|i| model.nodes.get(*i)) .expect("failed to find neck joint") .transform; + let redis = redis::Client::open("redis://shiro").unwrap(); + let redis_conn = redis.get_connection().unwrap(); Self { assets: assets::Assets::new(ctx), + redis, redis_conn, model, model_neck_base, fig_binary: fig::BinaryClient::new("shiro:32051", &[ @@ -166,6 +171,9 @@ impl teleia::state::Game for Overlays { for ov in self.overlays.iter_mut() { ov.handle_binary(ctx, st, &mut self.state, &msg)?; } + if let Ok(t) = str::from_utf8(&msg.event) { + log::info!("incoming: {}", t); + } match &*msg.event { b"overlay reset" => self.reset(ctx, st)?, b"overlay tracking" => { @@ -206,8 +214,8 @@ impl teleia::state::Game for Overlays { b"overlay info emacs cursor" => { let res: Erm<()> = (|| { let mut reader = std::io::Cursor::new(&msg.data); - let cursor_x = reader.read_f32::<LE>()?; - let cursor_y = reader.read_f32::<LE>()?; + let cursor_x = fig::read_length_prefixed_utf8(&mut reader)?.parse()?; + let cursor_y = fig::read_length_prefixed_utf8(&mut reader)?.parse()?; self.state.info.emacs_cursor = (cursor_x, cursor_y); Ok(()) })(); @@ -223,8 +231,8 @@ impl teleia::state::Game for Overlays { let mut reader = std::io::Cursor::new(&msg.data); let author = fig::read_length_prefixed_utf8(&mut reader)?; let msg = fig::read_length_prefixed_utf8(&mut reader)?; - let time = reader.read_f32::<LE>()?; - let biblicality = reader.read_f32::<LE>()?; + let time = fig::read_length_prefixed_utf8(&mut reader)?.parse()?; + let biblicality = fig::read_length_prefixed_utf8(&mut reader)?.parse()?; self.state.chat.author = author; self.state.chat.msg = msg; self.state.chat.time = time; diff --git a/crates/renderer/src/overlay/tcg.rs b/crates/renderer/src/overlay/tcg.rs index 5c6c16a..4191e6c 100644 --- a/crates/renderer/src/overlay/tcg.rs +++ b/crates/renderer/src/overlay/tcg.rs @@ -4,8 +4,10 @@ use glow::HasContext; use crate::overlay; -pub const WIDTH: f32 = 320.0; -pub const HEIGHT: f32 = 450.0; +pub const IWIDTH: usize = 160; +pub const IHEIGHT: usize = 225; +pub const WIDTH: f32 = IWIDTH as f32; +pub const HEIGHT: f32 = IHEIGHT as f32; #[derive(Debug, Clone)] enum Error { @@ -20,6 +22,7 @@ impl std::fmt::Display for Error { } impl std::error::Error for Error {} +#[derive(Debug, Clone)] struct Card { name: String, ty: String, @@ -27,37 +30,239 @@ struct Card { element: String, color: glam::Vec4, faction: String, + faction_color: glam::Vec4, equity: i64, - boost_level: i64, + boost_level: String, rarity: String, rarity_level: i64, body_text: String, base_image_name: String, + set: String, + minted_date: String, flags: String, } +struct RenderedCardSlot { + card: Option<Card>, + texture: texture::Texture, +} +impl RenderedCardSlot { + pub fn new(ctx: &context::Context) -> Self { + Self { + card: None, + texture: texture::Texture::new_empty(ctx), + } + } + pub fn set(&mut self, ctx: &context::Context, card: Card, img: &image::RgbaImage) { + self.card = Some(card); + unsafe { + self.texture.bind(ctx); + ctx.gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::RGBA as i32, + img.width() as i32, + img.height() as i32, + 0, + glow::RGBA, + glow::UNSIGNED_BYTE, + Some(&img.as_bytes()), + ); + ctx.gl.generate_mipmap(glow::TEXTURE_2D); + } + } + pub fn render(&self, + ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, + pos: glam::Vec2, + dim: glam::Vec2, + ) { + st.bind_2d(ctx, &ost.assets.shader_tcg_screen); + self.texture.bind(ctx); + ost.assets.shader_tcg_screen.set_position_2d(ctx, st, &pos, &dim); + st.mesh_square.render(ctx); + } +} + +fn load_texture(tex: &texture::Texture, ctx: &context::Context, st: &mut state::State, path: &str) -> Erm<()> { + unsafe { + let img = image::ImageReader::open(path)?.decode()?.into_rgba8(); + tex.bind(ctx); + ctx.gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::RGBA as i32, + img.width() as i32, + img.height() as i32, + 0, + glow::RGBA, + glow::UNSIGNED_BYTE, + Some(&img.as_bytes()), + ); + ctx.gl.generate_mipmap(glow::TEXTURE_2D); + Ok(()) + } +} + pub struct Overlay { fb: framebuffer::Framebuffer, - texture: texture::Texture, - shader_color: shader::Shader, - shader_screen: shader::Shader, - shader: shader::Shader, - font: font::TrueType, - card: Option<Card>, + texture_base: texture::Texture, + texture_art: texture::Texture, + texture_faction_nate: texture::Texture, + texture_faction_lever: texture::Texture, + texture_faction_tony: texture::Texture, + // font: font::TrueType, + font: font::Bitmap, + card: RenderedCardSlot, } impl Overlay { pub fn new(ctx: &context::Context) -> Self { Self { fb: framebuffer::Framebuffer::new(ctx, &glam::Vec2::new(WIDTH, HEIGHT), &glam::Vec2::new(0.0, 0.0)), - texture: texture::Texture::new_empty(ctx), - shader_color: shader::Shader::new(ctx, include_str!("../assets/shaders/color/vert.glsl"), include_str!("../assets/shaders/color/frag.glsl")), - shader_screen: shader::Shader::new(ctx, include_str!("../assets/shaders/tcg_screen/vert.glsl"), include_str!("../assets/shaders/tcg_screen/frag.glsl")), - shader: shader::Shader::new(ctx, include_str!("../assets/shaders/tcg/vert.glsl"), include_str!("../assets/shaders/tcg/frag.glsl")), - font: font::TrueType::new(ctx, 20.0, include_bytes!("../assets/fonts/iosevka-comfy-regular.ttf")), - card: None, + texture_base: texture::Texture::new_empty(ctx), + texture_art: texture::Texture::new_empty(ctx), + texture_faction_nate: texture::Texture::new(ctx, include_bytes!("../assets/textures/tcg/factions/nate.png")), + texture_faction_lever: texture::Texture::new(ctx, include_bytes!("../assets/textures/tcg/factions/lever.png")), + texture_faction_tony: texture::Texture::new(ctx, include_bytes!("../assets/textures/tcg/factions/tony.png")), + // font: font::TrueType::new(ctx, 32.0, include_bytes!("../assets/fonts/iosevka-comfy-regular.ttf")), + font: font::Bitmap::from_image(ctx, 6, 12, 96, 72, include_bytes!("../assets/fonts/terminus.png")), + card: RenderedCardSlot::new(ctx), } } + fn draw_rectangle(&self, + ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, + color: glam::Vec4, pos: glam::Vec2, dims: glam::Vec2 + ) { + st.bind_2d(ctx, &ost.assets.shader_color); + ost.assets.shader_color.set_vec4(ctx, "color", &color); + ost.assets.shader_color.set_position_2d( + ctx, st, + &pos, &dims, + ); + st.mesh_square.render(ctx); + } + + fn generate_card(&self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, card: Card) -> Option<image::RgbaImage> { + st.bind_framebuffer(ctx, &self.fb); + ctx.clear(); + + st.bind_2d(ctx, &ost.assets.shader_tcg_base); + self.texture_base.bind(ctx); + ost.assets.shader_tcg_base.set_vec4(ctx, "shift_color", &card.color); + ost.assets.shader_tcg_base.set_mat4(ctx, "view", &glam::Mat4::IDENTITY); + ost.assets.shader_tcg_base.set_mat4(ctx, "position", &glam::Mat4::IDENTITY); + st.mesh_square.render(ctx); + + // top bar + self.draw_rectangle(ctx, st, ost, + card.color.clone(), + glam::Vec2::new(0.0, 0.0), + glam::Vec2::new(WIDTH, 16.0), + ); + self.font.render_text_helper(ctx, st, + &glam::Vec2::new(8.0, 1.0), + &card.name, + &[glam::Vec3::new(0.0, 0.0, 0.0)] + ); + self.font.render_text_helper(ctx, st, + &glam::Vec2::new(WIDTH - 8.0 * card.rarity.len() as f32, 1.0), + &card.rarity, + &[glam::Vec3::new(0.0, 0.0, 0.0)] + ); + + // art + self.draw_rectangle(ctx, st, ost, + glam::Vec4::new(0.1, 0.1, 0.1, 1.0), + glam::Vec2::new(10.0, 16.0), + glam::Vec2::new(140.0, 100.0), + ); + st.bind_2d(ctx, &ost.assets.shader_flat); + self.texture_art.bind(ctx); + ost.assets.shader_flat.set_position_2d( + ctx, st, + &glam::Vec2::new(10.0, 16.0), + &glam::Vec2::new(140.0, 100.0) + ); + st.mesh_square.render(ctx); + + // faction stamp + let stex = match card.faction.as_ref() { + "nate" => Some(&self.texture_faction_nate), + "lever" => Some(&self.texture_faction_lever), + "tony" => Some(&self.texture_faction_tony), + _ => None, + }; + if let Some(tex) = stex { + st.bind_2d(ctx, &ost.assets.shader_flat); + tex.bind(ctx); + ost.assets.shader_flat.set_position_2d( + ctx, st, + &glam::Vec2::new(WIDTH - 12.0 - 32.0, 18.0), + &glam::Vec2::new(32.0, 32.0) + ); + st.mesh_square.render(ctx); + } + + // boost text + let boost_pos = glam::Vec2::new(12.0, 105.0); + self.font.render_text_helper(ctx, st, + &boost_pos, + &card.boost_level, + &[glam::Vec3::new(0.1, 0.1, 0.1)] + ); + self.font.render_text_helper(ctx, st, + &(boost_pos - glam::Vec2::new(1.0, 1.0)), + &card.boost_level, + &[glam::Vec3::new(0.9, 0.9, 0.9)] + ); + + // equity marks + let equity_pos = glam::Vec2::new(12.0, 18.0); + for i in 0..card.equity { + self.font.render_text_helper(ctx, st, + &(equity_pos + glam::Vec2::new(0.0, 10.0) * i as f32), + "$", + &[glam::Vec3::new(0.1, 0.1, 0.1)] + ); + } + + // body text + self.draw_rectangle(ctx, st, ost, + glam::Vec4::new(1.0, 1.0, 1.0, 0.5), + glam::Vec2::new(4.0, 119.0), + glam::Vec2::new(152.0, 100.0), + ); + for (i, cs) in card.body_text.chars().collect::<Vec<char>>().chunks(25).enumerate() { + let line: String = cs.iter().collect(); + self.font.render_text_helper(ctx, st, + &glam::Vec2::new(5.0, 120.0 + 10.0 * i as f32), + &format!("{}", line), + &[glam::Vec3::new(0.2, 0.2, 0.2)] + ); + } + + // bottom bar + self.draw_rectangle(ctx, st, ost, + glam::Vec4::new(0.0, 0.0, 0.0, 0.8), + glam::Vec2::new(0.0, HEIGHT - 16.0), + glam::Vec2::new(WIDTH, 16.0), + ); + self.font.render_text_helper(ctx, st, + &glam::Vec2::new(1.0, HEIGHT - 15.0), + &format!("{}", card.set), + &[glam::Vec3::new(1.0, 1.0, 1.0)] + ); + self.font.render_text_helper(ctx, st, + &glam::Vec2::new(WIDTH - 7.0 * (card.minted_date.len() - 1) as f32, HEIGHT - 15.0), + &format!("{}", card.minted_date), + &[glam::Vec3::new(1.0, 1.0, 1.0)] + ); + + st.bind_render_framebuffer(ctx); + let mut pixels = vec![0; IWIDTH * IHEIGHT * 4]; + self.fb.get_pixels_raw(ctx, &mut pixels); + image::RgbaImage::from_vec(IWIDTH as u32, IHEIGHT as u32, pixels) + } } impl overlay::Overlay for Overlay { @@ -69,6 +274,7 @@ impl overlay::Overlay for Overlay { b"overlay tcg generate" => { let res: Erm<()> = (|| { let s = std::str::from_utf8(&msg.data)?.to_owned(); + log::info!("msg: {}", s); let mut sp = s.split("\t"); let id = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); let name = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); @@ -80,43 +286,57 @@ impl overlay::Overlay for Overlay { let g = i64::from_str_radix(&color[3..=4], 16)?; let b = i64::from_str_radix(&color[5..=6], 16)?; let faction = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); + let faction_color = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); + let f_r = i64::from_str_radix(&faction_color[1..=2], 16)?; + let f_g = i64::from_str_radix(&faction_color[3..=4], 16)?; + let f_b = i64::from_str_radix(&faction_color[5..=6], 16)?; let equity = sp.next().ok_or(Error::NotEnoughFields)?.parse()?; - let boost_level = sp.next().ok_or(Error::NotEnoughFields)?.parse()?; + let boost_level = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); let rarity = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); let rarity_level = sp.next().ok_or(Error::NotEnoughFields)?.parse()?; let body_text = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); let base_image_name = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); + let set = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); + let minted_date = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); let flags = sp.next().ok_or(Error::NotEnoughFields)?.to_owned(); - unsafe { - let img = image::ImageReader::open(format!("crates/renderer/src/assets/textures/tcg/bases/{}.png", base_image_name))?.decode()?.into_rgba8(); - self.texture.bind(ctx); - ctx.gl.tex_image_2d( - glow::TEXTURE_2D, - 0, - glow::RGBA as i32, - img.width() as i32, - img.height() as i32, - 0, - glow::RGBA, - glow::UNSIGNED_BYTE, - Some(&img.as_bytes()), - ); - ctx.gl.generate_mipmap(glow::TEXTURE_2D); + load_texture(&self.texture_base, ctx, st, &format!("crates/renderer/src/assets/textures/tcg/bases/{}.png", base_image_name))?; + if load_texture(&self.texture_art, ctx, st, &format!("/home/llll/src/wasp/assets/avatars/{}.png", depicted_subject.to_ascii_lowercase())).is_err() { + load_texture(&self.texture_art, ctx, st, "/home/llll/src/wasp/assets/avatars/jontest.png")?; } - self.card = Some(Card { + let card = Card { name, ty, depicted_subject, element, color: glam::Vec4::new(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0, 1.0), faction, + faction_color: glam::Vec4::new(f_r as f32 / 255.0, f_g as f32 / 255.0, f_b as f32 / 255.0, 1.0), equity, boost_level, rarity, rarity_level, body_text, base_image_name, + set, + minted_date, flags, - }); + }; + if let Some(img) = self.generate_card(ctx, st, ost, card.clone()) { + self.card.set(ctx, card, &img); + let err: Erm<()> = (||{ + let mut buf = Vec::new(); + let mut cursor = std::io::Cursor::new(&mut buf); + img.write_to(&mut cursor, image::ImageFormat::Png)?; + let with_meta = web_image_meta::png::add_text_chunk( + &buf, "lcolonqtcg", &s + )?; + // TODO: write to redis here + std::fs::write("/tmp/card.png", &with_meta)?; + Ok(()) + })(); + if let Err(e) = err { + log::warn!("failed to encode image: {}", e) + } + } Ok(()) })(); if let Err(e) = res { log::warn!("malformed TCG generate: {}", e); } @@ -126,42 +346,11 @@ impl overlay::Overlay for Overlay { Ok(()) } fn render(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { - if let Some(card) = &self.card { - st.bind_framebuffer(ctx, &self.fb); - ctx.clear(); - - st.bind_2d(ctx, &ost.assets.shader_flat); - self.texture.bind(ctx); - ost.assets.shader_flat.set_f32(ctx, "transparency", 0.0); - ost.assets.shader_flat.set_mat4(ctx, "view", &glam::Mat4::IDENTITY); - ost.assets.shader_flat.set_mat4(ctx, "position", &glam::Mat4::IDENTITY); - st.mesh_square.render(ctx); - - st.bind_2d(ctx, &self.shader_color); - self.shader_color.set_vec4(ctx, "color", &glam::Vec4::new(1.0, 0.0, 0.0, 1.0)); - self.shader_color.set_position_2d( - ctx, st, - &glam::Vec2::new(0.0, 10.0), - &glam::Vec2::new(WIDTH, 32.0) + if self.card.card.is_some() { + self.card.render(ctx, st, ost, + glam::Vec2::new(1000.0, 400.0), + glam::Vec2::new(WIDTH * 2.0, HEIGHT * 2.0) ); - st.mesh_square.render(ctx); - - self.font.render_text_helper(ctx, st, - &glam::Vec2::new(0.0, 0.0), - &glam::Vec2::new(21.0, 40.0), - &card.name, - &[] - ); - - st.bind_render_framebuffer(ctx); - st.bind_2d(ctx, &self.shader_screen); - self.fb.bind_texture(ctx); - self.shader_screen.set_position_2d( - ctx, st, - &glam::Vec2::new(1000.0, 200.0), - &glam::Vec2::new(WIDTH, HEIGHT) - ); - st.mesh_square.render(ctx); } Ok(()) } |
