summaryrefslogtreecommitdiff
path: root/crates/renderer/src/overlay
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2025-09-16 01:36:57 -0400
committerLLLL Colonq <llll@colonq>2025-09-16 01:36:57 -0400
commit4ae21efc81f39ca805cefe5c1af722857f22f255 (patch)
treed877c34b806c61e9480f1c209fd104fffee43988 /crates/renderer/src/overlay
parent4db7ffbaafda249ecafa720e52479d5c7b132edb (diff)
Add poster maker
Diffstat (limited to 'crates/renderer/src/overlay')
-rw-r--r--crates/renderer/src/overlay/irish.rs113
-rw-r--r--crates/renderer/src/overlay/model.rs4
-rw-r--r--crates/renderer/src/overlay/shader.rs2
3 files changed, 116 insertions, 3 deletions
diff --git a/crates/renderer/src/overlay/irish.rs b/crates/renderer/src/overlay/irish.rs
new file mode 100644
index 0000000..6cf3d52
--- /dev/null
+++ b/crates/renderer/src/overlay/irish.rs
@@ -0,0 +1,113 @@
+use teleia::*;
+
+use lexpr::sexp;
+use base64::prelude::*;
+
+use crate::{fig, overlay, toggle};
+
+pub const WIDTH: f32 = 500.0;
+pub const HEIGHT: f32 = 700.0;
+
+pub struct Quote {
+ text: String,
+ start_time: u64,
+}
+
+pub struct Overlay {
+ fb: framebuffer::Framebuffer,
+ shader: shader::Shader,
+ font: font::TrueType,
+ quote: Option<Quote>,
+}
+
+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)),
+ shader: shader::Shader::new(ctx, include_str!("../assets/shaders/irish/vert.glsl"), include_str!("../assets/shaders/irish/frag.glsl")),
+ font: font::TrueType::new(ctx, 40.0, include_bytes!("../assets/fonts/HennyPenny-Regular.ttf")),
+ quote: None,
+ }
+ }
+ pub fn handle_start(
+ &mut self,
+ ctx: &context::Context, st: &state::State,
+ msg: fig::SexpMessage
+ ) -> Option<()> {
+ let bq = BASE64_STANDARD.decode(msg.data.get(0)?.as_str()?).ok()?;
+ let quote = String::from_utf8_lossy(&bq);
+ self.quote = Some(Quote { text: quote.to_string(), start_time: st.tick });
+ Some(())
+ }
+ pub fn handle_update(
+ &mut self,
+ ctx: &context::Context, st: &state::State,
+ msg: fig::SexpMessage
+ ) -> Option<()> {
+ let bq = BASE64_STANDARD.decode(msg.data.get(0)?.as_str()?).ok()?;
+ let quote = String::from_utf8_lossy(&bq);
+ if let Some(q) = &mut self.quote {
+ q.text = quote.to_string();
+ }
+ Some(())
+ }
+ pub fn handle_save(
+ &mut self,
+ ctx: &context::Context, st: &state::State,
+ msg: fig::SexpMessage
+ ) -> Option<()> {
+ let bq = BASE64_STANDARD.decode(msg.data.get(0)?.as_str()?).ok()?;
+ let path = String::from_utf8_lossy(&bq);
+ let mut buf = vec![0; (WIDTH * HEIGHT * 4.0) as usize];
+ self.fb.get_pixels_raw(ctx, &mut buf);
+ let img = image::RgbaImage::from_raw(WIDTH as u32, HEIGHT as u32, buf)?;
+ img.save_with_format(path.to_string(), image::ImageFormat::Png).ok()?;
+ Some(())
+ }
+}
+
+impl overlay::Overlay for Overlay {
+ fn reset(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> {
+ self.quote = None;
+ Ok(())
+ }
+ fn handle(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: fig::SexpMessage) -> Erm<()> {
+ let malformed = format!("malformed {} data: {}", msg.event, msg.data);
+ if msg.event == sexp!((overlay irish start)) {
+ if self.handle_start(ctx, st, msg).is_none() { log::warn!("{}", malformed) }
+ } else if msg.event == sexp!((overlay irish update)) {
+ if self.handle_update(ctx, st, msg).is_none() { log::warn!("{}", malformed) }
+ } else if msg.event == sexp!((overlay irish save)) {
+ if self.handle_save(ctx, st, msg).is_none() { log::warn!("{}", malformed) }
+ }
+ Ok(())
+ }
+ fn render(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> {
+ if let Some(q) = &self.quote {
+ st.bind_framebuffer(ctx, &self.fb);
+ ctx.clear();
+ st.bind_2d(ctx, &ost.assets.shader_flat);
+ ost.backgrounds.drawing.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);
+ self.font.render_text_helper(ctx, st,
+ &glam::Vec2::new(0.0, 0.0),
+ &glam::Vec2::new(21.0, 40.0),
+ &q.text,
+ &[]
+ );
+ st.bind_render_framebuffer(ctx);
+ st.bind_2d(ctx, &self.shader);
+ self.fb.bind_texture(ctx);
+ self.shader.set_position_2d(
+ ctx,
+ &glam::Vec2::new(1000.0, 200.0),
+ &glam::Vec2::new(WIDTH, HEIGHT)
+ );
+ st.mesh_square.render(ctx);
+ }
+ Ok(())
+ }
+}
diff --git a/crates/renderer/src/overlay/model.rs b/crates/renderer/src/overlay/model.rs
index 98b008e..26c06bf 100644
--- a/crates/renderer/src/overlay/model.rs
+++ b/crates/renderer/src/overlay/model.rs
@@ -52,7 +52,7 @@ impl teleia::state::Game for Terminal {
self.terminal.update(ctx, &self.model_fb);
ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 0.0));
ctx.clear();
- self.terminal.render(ctx, &glam::Vec2::new(12.0, 250.0));
+ self.terminal.render(ctx, st, &glam::Vec2::new(12.0, 250.0));
Ok(())
}
}
@@ -119,7 +119,7 @@ impl overlay::Overlay for Overlay {
self.terminal.update(ctx, &self.model_fb);
ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 0.0));
ctx.clear();
- self.terminal.render(ctx, &glam::Vec2::new(12.0, 250.0));
+ self.terminal.render(ctx, st, &glam::Vec2::new(12.0, 250.0));
st.projection = old_projection;
Ok(())
}
diff --git a/crates/renderer/src/overlay/shader.rs b/crates/renderer/src/overlay/shader.rs
index 11133bf..dd35031 100644
--- a/crates/renderer/src/overlay/shader.rs
+++ b/crates/renderer/src/overlay/shader.rs
@@ -93,7 +93,7 @@ impl overlay::Overlay for Overlay {
authors.push(format!("music by {}", a));
}
let astr: String = authors.join(", ");
- ost.assets.font.render_text(ctx, &glam::Vec2::new(0.0, 0.0), &astr);
+ ost.assets.font.render_text(ctx, st, &glam::Vec2::new(0.0, 0.0), &astr);
Ok(())
}
}