--- /dev/null
+package bmfont
+
+#private_file math :: package core.math
+
+@Incomplete // does not use the size parameter
+get_width :: (use font: ^BMFont, text: str, size: f32) -> f32 {
+ max_x := 0.0f;
+ x := 0.0f;
+
+ for char: text {
+ if char == #char "\n" {
+ max_x = math.max(max_x, x);
+ x = 0.0f;
+ continue;
+ }
+
+ glyph := font->get_glyph(char);
+
+ if glyph == null {
+ glyph = font->get_glyph(0);
+ }
+
+ x += ~~ glyph.xadvance * size;
+ }
+
+ return math.max(max_x, x);
+}
+
+@Incomplete // does not use the size parameter
+get_height :: (use font: ^BMFont, text: str, size: f32) -> f32 {
+ max_y := 0.0f;
+ y := 0.0f;
+
+ for char: text {
+ if char == #char "\n" {
+ y += max_y;
+ max_y = 0;
+ continue;
+ }
+
+ glyph := font->get_glyph(char);
+
+ if glyph == null {
+ glyph = font->get_glyph(0);
+ }
+
+ max_y = math.max(max_y, ~~glyph.h * size);
+ }
+
+ return y + max_y;
+}
\ No newline at end of file
--- /dev/null
+#version 300 es
+
+precision mediump float;
+
+uniform sampler2D u_texture;
+
+in vec4 v_color;
+in vec2 v_texture;
+
+out vec4 fragColor;
+
+void main() {
+ float alpha = texture(u_texture, v_texture).a;
+ fragColor = v_color * alpha;
+}
\ No newline at end of file
}
if is_hot_item(hash) {
- move_towards(^button_state.hover_time, 1.0f, 0.1f);
+ move_towards(^button_state.hover_time, 1.0f, 0.1f); @ThemeConfiguration
} else {
- move_towards(^button_state.hover_time, 0.0f, 0.1f);
+ move_towards(^button_state.hover_time, 0.0f, 0.1f); @ThemeConfiguration
}
- move_towards(^button_state.click_time, 0.0f, 0.08f);
+ move_towards(^button_state.click_time, 0.0f, 0.08f); @ThemeConfiguration
border_width := theme.border_width;
width, height := Rectangle.dimensions(r);
surface_color = color_lerp(button_state.click_time, surface_color, theme.click_color);
gfx.rect(.{ x0 + border_width, y0 + border_width }, .{ width - border_width * 2, height - border_width * 2 }, surface_color);
- text_width := 0.0f; @Cleanup // font->get_width(text, theme.font_size);
- text_height := 0.0f; @Cleanup // font->get_height(text, theme.font_size);
+ text_width := bmfont.get_width(^font, text, theme.font_size);
+ text_height := bmfont.get_height(^font, text, theme.font_size);
- draw_text_raw(text, x0 + (width - text_width) / 2, y0 + (height - text_height) / 2, theme.font_size, theme.text_color);
+ @ThemeConfiguration // This always draws the text centered on the button surface.
+ draw_text_raw(text, x0 + (width - text_width) / 2, y0 + ~~ font.common.baseline * theme.font_size + (height - text_height) / 2, theme.font_size, theme.text_color);
if button_state.click_time > 0 || button_state.hover_time > 0 {
map.put(^button_states, hash, button_state);
--- /dev/null
+info face="Fira Code Retina" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 outline=0
+common lineHeight=32 base=24 scaleW=256 scaleH=256 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
+page id=0 file="test_0.tga"
+chars count=96
+char id=-1 x=159 y=0 width=16 height=22 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
+char id=32 x=252 y=0 width=3 height=1 xoffset=-1 yoffset=31 xadvance=16 page=0 chnl=15
+char id=33 x=249 y=42 width=6 height=19 xoffset=5 yoffset=5 xadvance=16 page=0 chnl=15
+char id=34 x=226 y=79 width=10 height=7 xoffset=3 yoffset=4 xadvance=16 page=0 chnl=15
+char id=35 x=129 y=46 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=36 x=5 y=0 width=14 height=28 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=15
+char id=37 x=97 y=26 width=16 height=20 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=38 x=98 y=47 width=15 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=39 x=237 y=79 width=4 height=7 xoffset=6 yoffset=4 xadvance=16 page=0 chnl=15
+char id=40 x=56 y=0 width=10 height=27 xoffset=2 yoffset=1 xadvance=16 page=0 chnl=15
+char id=41 x=67 y=0 width=10 height=27 xoffset=4 yoffset=1 xadvance=16 page=0 chnl=15
+char id=42 x=161 y=86 width=14 height=14 xoffset=1 yoffset=8 xadvance=16 page=0 chnl=15
+char id=43 x=176 y=84 width=14 height=13 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=44 x=191 y=83 width=6 height=10 xoffset=5 yoffset=19 xadvance=16 page=0 chnl=15
+char id=45 x=17 y=71 width=12 height=3 xoffset=2 yoffset=13 xadvance=16 page=0 chnl=15
+char id=46 x=17 y=111 width=6 height=5 xoffset=5 yoffset=19 xadvance=16 page=0 chnl=15
+char id=47 x=96 y=0 width=14 height=25 xoffset=1 yoffset=2 xadvance=16 page=0 chnl=15
+char id=48 x=15 y=75 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=49 x=44 y=71 width=13 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=50 x=72 y=70 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=51 x=100 y=67 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=52 x=114 y=26 width=14 height=20 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
+char id=53 x=128 y=67 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=54 x=0 y=75 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=55 x=129 y=25 width=12 height=20 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=56 x=114 y=47 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=57 x=237 y=0 width=14 height=21 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=58 x=154 y=86 width=6 height=15 xoffset=5 yoffset=9 xadvance=16 page=0 chnl=15
+char id=59 x=142 y=25 width=6 height=20 xoffset=5 yoffset=9 xadvance=16 page=0 chnl=15
+char id=60 x=128 y=87 width=12 height=15 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15
+char id=61 x=213 y=79 width=12 height=8 xoffset=2 yoffset=11 xadvance=16 page=0 chnl=15
+char id=62 x=60 y=90 width=13 height=15 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15
+char id=63 x=181 y=63 width=12 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=64 x=176 y=0 width=16 height=22 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=65 x=17 y=51 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=66 x=114 y=67 width=13 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=67 x=82 y=50 width=15 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=68 x=50 y=50 width=15 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=69 x=86 y=70 width=13 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=70 x=168 y=64 width=12 height=19 xoffset=3 yoffset=5 xadvance=16 page=0 chnl=15
+char id=71 x=34 y=51 width=15 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=72 x=204 y=43 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=73 x=155 y=66 width=12 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=74 x=58 y=70 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=75 x=189 y=43 width=14 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=76 x=142 y=66 width=12 height=19 xoffset=3 yoffset=5 xadvance=16 page=0 chnl=15
+char id=77 x=0 y=55 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=78 x=159 y=44 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=79 x=168 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=80 x=234 y=43 width=14 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=81 x=126 y=0 width=17 height=24 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=82 x=144 y=46 width=14 height=19 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
+char id=83 x=66 y=50 width=15 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=84 x=236 y=22 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=85 x=174 y=43 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=86 x=219 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=87 x=149 y=24 width=18 height=19 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=88 x=202 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=89 x=185 y=23 width=16 height=19 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
+char id=90 x=219 y=43 width=14 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=91 x=78 y=0 width=8 height=26 xoffset=4 yoffset=1 xadvance=16 page=0 chnl=15
+char id=92 x=111 y=0 width=14 height=25 xoffset=1 yoffset=2 xadvance=16 page=0 chnl=15
+char id=93 x=87 y=0 width=8 height=26 xoffset=4 yoffset=1 xadvance=16 page=0 chnl=15
+char id=94 x=198 y=79 width=14 height=9 xoffset=1 yoffset=0 xadvance=16 page=0 chnl=15
+char id=95 x=24 y=111 width=14 height=3 xoffset=1 yoffset=26 xadvance=16 page=0 chnl=15
+char id=96 x=242 y=79 width=8 height=5 xoffset=4 yoffset=3 xadvance=16 page=0 chnl=15
+char id=97 x=45 y=91 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=98 x=56 y=28 width=13 height=21 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15
+char id=99 x=243 y=63 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
+char id=100 x=42 y=28 width=13 height=21 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
+char id=101 x=228 y=63 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=102 x=28 y=29 width=13 height=21 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15
+char id=103 x=144 y=0 width=14 height=23 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15
+char id=104 x=84 y=27 width=12 height=21 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15
+char id=105 x=208 y=0 width=13 height=22 xoffset=2 yoffset=2 xadvance=16 page=0 chnl=15
+char id=106 x=20 y=0 width=11 height=28 xoffset=2 yoffset=2 xadvance=16 page=0 chnl=15
+char id=107 x=193 y=0 width=14 height=22 xoffset=2 yoffset=2 xadvance=16 page=0 chnl=15
+char id=108 x=0 y=33 width=13 height=21 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
+char id=109 x=211 y=63 width=16 height=15 xoffset=0 yoffset=9 xadvance=16 page=0 chnl=15
+char id=110 x=102 y=87 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
+char id=111 x=0 y=95 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=112 x=70 y=28 width=13 height=21 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
+char id=113 x=14 y=29 width=13 height=21 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=114 x=74 y=90 width=13 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
+char id=115 x=88 y=90 width=13 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=116 x=30 y=71 width=13 height=19 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
+char id=117 x=115 y=87 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
+char id=118 x=15 y=95 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=119 x=194 y=63 width=16 height=15 xoffset=0 yoffset=9 xadvance=16 page=0 chnl=15
+char id=120 x=30 y=91 width=14 height=15 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=121 x=222 y=0 width=14 height=21 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
+char id=122 x=141 y=87 width=12 height=15 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
+char id=123 x=44 y=0 width=11 height=27 xoffset=2 yoffset=1 xadvance=16 page=0 chnl=15
+char id=124 x=0 y=0 width=4 height=32 xoffset=6 yoffset=0 xadvance=16 page=0 chnl=15
+char id=125 x=32 y=0 width=11 height=27 xoffset=3 yoffset=1 xadvance=16 page=0 chnl=15
+char id=126 x=0 y=111 width=16 height=5 xoffset=0 yoffset=13 xadvance=16 page=0 chnl=15
#private font_texture : gl.GLTexture;
@Temporary
-DEFAULT_TEXT_SIZE :: 40.0f
+DEFAULT_TEXT_SIZE :: 1.0f
UI_Id :: #type u32
init_ui :: () {
init_font();
- map.init(^button_states, default=.{});
+ map.init(^button_states, default=.{}, hash_count=4);
}
clear_buttons :: () {
return hot_item == id;
}
-draw_text_raw :: (text: str, x: f32, y: f32, line_height := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) {
+draw_text_raw :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) {
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, font_texture);
- gfx.set_texture(0);
+ gfx.use_alpha_shader(0);
original_x := x;
- baseline := cast(f32) font.common.baseline;
+ baseline := cast(f32) font.common.baseline * size;
+
+ line_height := cast(f32) font.common.line_height * size;
for char: text {
if char == #char "\n" {
assert(glyph != null, "NO NULL GLYPH");
}
- // Round to the nearest pixel
- tx, ty := math.floor(x + ~~glyph.xoffset + .5), math.floor(y + ~~glyph.yoffset + baseline + .5);
- w := math.floor(cast(f32) glyph.w + .5);
- h := math.floor(cast(f32) glyph.h + .5);
+ // Round to the nearest pixel to avoid bleeding to the next glyph
+ tx, ty := math.floor(x + ~~glyph.xoffset * size + .5), math.floor(y + ~~glyph.yoffset * size - baseline + .5);
+ w := math.floor(cast(f32) glyph.w * size + .5);
+ h := math.floor(cast(f32) glyph.h * size + .5);
- gfx.textured_rect(
- .{ tx, ty },
- .{ w, h },
- .{ glyph.tex_x, glyph.tex_y },
- .{ glyph.tex_w, glyph.tex_h },
- color = color);
+ gfx.textured_rect(.{ tx, ty }, .{ w, h }, .{ glyph.tex_x, glyph.tex_y }, .{ glyph.tex_w, glyph.tex_h }, color = color);
- x += ~~glyph.xadvance;
+ x += ~~glyph.xadvance * size;
}
gfx.flush();
@Themeing
draw_text :: (use r: Rectangle, text: str, theme := ^default_text_theme, site := #callsite) -> bool {
- draw_text_raw(text, x0, y0, theme.font_size, theme.text_color);
+ draw_text_raw(text, x0, y0 + ~~font.common.baseline * theme.font_size, theme.font_size, theme.text_color);
}
Rectangle :: struct {
@Relocate
Text_Theme :: struct {
text_color := gfx.Color4.{ 1, 1, 1 };
- font_size := 18.0f;
+ font_size := 1.0f;
}
default_text_theme: Text_Theme = Text_Theme.{};
}
get_text_width :: (text: str, size := DEFAULT_TEXT_SIZE) -> f32 {
- @Cleanup
- return 0; // font->get_width(text, size);
+ return font->get_width(text, size);
}
+@Cleanup
+// There should be a way to load multiple fonts and have a font cache.
+// The font cache pointers should be stable so you can take a pointer
+// to a font and it will remain valid. Probably want some kind of arena
+// with a map from i32 -> ^BMFont.
#private init_font :: () {
- fnt_file_data := #file_contents "./resources/fonts/FiraCode.fnt";
- texture_data := #file_contents "./resources/fonts/FiraCode.data";
+ fnt_file_data := #file_contents "./resources/fonts/test.fnt";
+ texture_data := #file_contents "./resources/fonts/test_0.data";
font = bmfont.load_bmfont(fnt_file_data);
font_texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, font_texture);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, tex_width, tex_height, 0, gl.RGBA, gl.UNSIGNED_BYTE, texture_data);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, tex_width, tex_height, 0, gl.ALPHA, gl.UNSIGNED_BYTE, texture_data);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
// Polymorphic Procedures
//
-AstNode node_that_signals_a_yield = {};
+AstNode node_that_signals_a_yield = { 0 };
static void ensure_polyproc_cache_is_created(AstPolyProc* pp) {
if (pp->concrete_funcs == NULL) {