summaryrefslogtreecommitdiff
path: root/crates/renderer/src/overlay/model.rs
blob: 9714f09647a32e5dbd9379af9cc4fbfc97967671 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use teleia::*;
use termion::raw::IntoRawMode;

use std::f32::consts::PI;
use lexpr::sexp;
use base64::prelude::*;

use crate::{overlay, terminal};

pub struct Terminal {
    ost: overlay::State,
    output: termion::raw::RawTerminal<std::io::Stdout>,
    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
            ),
        }
    }
    pub fn handle_text(&mut self, msg: fig::SexpMessage) -> Option<()> {
        let bs = BASE64_STANDARD.decode(msg.data.get(0)?.as_str()?).ok()?;
        let s = std::str::from_utf8(&bs).ok()?;
        log::info!("handle_text: {}", s);
        self.terminal.fill_string(s);
        Some(())
    }
    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(&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!((avatar text)) {
            if self.handle_text(msg).is_none() { log::warn!("{}", malformed) }
        }
        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(())
    }
}