use teleia::*; use termion::raw::IntoRawMode; use std::f32::consts::PI; use crate::{overlay, terminal}; pub struct Terminal { ost: overlay::State, output: termion::raw::RawTerminal, terminal: terminal::Terminal, model_fb: framebuffer::Framebuffer, } impl Terminal { pub fn new(ctx: &context::Context) -> Self { Self { ost: overlay::State::new(ctx), output: std::io::stdout().into_raw_mode().expect("failed to set raw mode"), terminal: terminal::Terminal::new(ctx, 64, 64), model_fb: framebuffer::Framebuffer::new( ctx, &glam::Vec2::new(64.0, 64.0), &glam::Vec2::ZERO ), } } } impl teleia::state::Game for Terminal { fn update(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { st.projection = glam::Mat4::perspective_lh( PI / 4.0, self.terminal.width as f32 / self.terminal.height as f32, 0.1, 10.0 ); Ok(()) } fn render(&mut self, ctx: &context::Context, st: &mut state::State) -> Erm<()> { self.model_fb.bind(ctx); ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 0.0)); ctx.clear(); st.bind_3d(ctx, &self.ost.assets.shader_scene); self.ost.assets.shader_scene.set_position_3d( ctx, st, &glam::Mat4::from_translation( glam::Vec3::new(0.0, -1.63, 0.42), ), ); self.ost.model.render(ctx, &self.ost.assets.shader_scene); st.render_framebuffer.bind(ctx); 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, st, &glam::Vec2::new(12.0, 250.0)); Ok(()) } } pub struct Overlay { terminal: terminal::Terminal, model_fb: framebuffer::Framebuffer, } impl Overlay { pub fn new(ctx: &context::Context) -> Self { Self { terminal: terminal::Terminal::new(ctx, 64, 64), model_fb: framebuffer::Framebuffer::new( ctx, &glam::Vec2::new(64.0, 64.0), &glam::Vec2::ZERO ), } } fn render_model(&mut self, ctx: &context::Context, st: &mut state::State) -> Option<()> { // self.model_fb.blit( // ctx, &st.render_framebuffer, // &glam::Vec2::new(ctx.render_width / 2.0 - 512.0, ctx.render_height / 2.0 - 512.0), // &glam::Vec2::new(128.0, 128.0) // ); Some(()) } } impl overlay::Overlay for Overlay { fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &fig::BinaryMessage) -> Erm<()> { if msg.event == b"overlay avatar text" { match str::from_utf8(&msg.data) { Ok(s) => self.terminal.fill_string(s), Err(e) => log::warn!("malformed avatar text update: {}", e), } } Ok(()) } fn render(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { let old_projection = st.projection; st.projection = glam::Mat4::perspective_lh( PI / 4.0, self.terminal.width as f32 / self.terminal.height as f32, 0.1, 10.0 ); self.model_fb.bind(ctx); ctx.clear_color(glam::Vec4::new(0.0, 0.0, 0.0, 0.0)); ctx.clear(); st.bind_3d(ctx, &ost.assets.shader_scene); ost.assets.shader_scene.set_position_3d( ctx, st, &glam::Mat4::from_translation( glam::Vec3::new(0.0, -1.63, 0.42), ), ); ost.model.render(ctx, &ost.assets.shader_scene); st.render_framebuffer.bind(ctx); 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, st, &glam::Vec2::new(12.0, 250.0)); st.projection = old_projection; Ok(()) } }