summaryrefslogtreecommitdiff
path: root/src/font.rs
blob: d35abf0f9c1f80ab4a3335cacd0d230742b4acbd (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
use crate::{context, texture, shader};

pub const CHAR_WIDTH: i32 = 7;
pub const CHAR_HEIGHT: i32 = 9;
pub const FONT_WIDTH: i32 = 112;
pub const FONT_HEIGHT: i32 = 54;

pub struct Font {
    pub shader: shader::Shader,
    pub font: texture::Texture,
}

impl Font {
    pub fn new(ctx: &context::Context) -> Self {
        let shader = shader::Shader::new_nolib(
            &ctx,
            include_str!("assets/shaders/text/vert.glsl"),
            include_str!("assets/shaders/text/frag.glsl"),
        );
        let font = texture::Texture::new(ctx, include_bytes!("assets/fonts/simple.png"));
        Self {
            shader,
            font,
        }
    }

    pub fn render_text(&self, ctx: &context::Context, pos: &glam::Vec2, text: &str) {
        let mut width = 0;
        let mut linewidth = 0;
        let mut height = CHAR_HEIGHT;
        for c in text.chars() {
            if c == '\n' {
                width = width.max(linewidth);
                linewidth = 0;
                height += CHAR_HEIGHT;
            } else {
                linewidth += CHAR_WIDTH; 
            }
        }
        width = width.max(linewidth);

        self.shader.bind(ctx);
        let len = text.len().min(256);
        self.shader.set_i32(ctx, "text_length", len as _);
        let textvals: Vec<i32> = 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_mat4(
            ctx, "view",
            &glam::Mat4::from_scale(
                glam::Vec3::new(
                    2.0 / context::RENDER_WIDTH,
                    2.0 / context::RENDER_HEIGHT,
                    1.0,
                ),
            ),
        );
        let halfwidth = width as f32 / 2.0;
        let halfheight = height as f32 / 2.0;
        self.shader.set_mat4(
            ctx, "position",
            &glam::Mat4::from_scale_rotation_translation(
                glam::Vec3::new(halfwidth, halfheight, 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,
                ),
            )
        );
        self.font.bind(ctx);
        ctx.render_no_geometry();
    }
}