#private_file gfx :: package immediate_mode
#private_file bitmap_font :: package bitmap_font
+#private_file ui :: package ui
-
-font : bitmap_font.Bitmap_Font;
-font_texture : gl.GLTexture;
-
main :: (args: [] cstr) {
gl.init("game");
events.init();
gfx.immediate_renderer_init();
- init_font();
+ ui.init_ui();
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
start_loop();
}
-init_font :: () {
- font_data := #file_contents "src/res/font_2.data";
-
- bft := bitmap_font.Bitmap_Font_Texture.{
- data = font_data,
- width = 256,
- height = 256,
- };
-
- font = bitmap_font.bitmap_font_create(bft, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \xff:");
-
- font_texture = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, font_texture);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, font_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);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
- gl.bindTexture(gl.TEXTURE_2D, -1);
-}
-
last_time := 0;
#export "loop" () {
time_now :: () -> i32 #foreign "game" "time_now" ---
}
}
-fps := 0;
-fps_timer := 1.0f;
-frames := 0
+#if DEBUG {
+ fps := 0
+ fps_timer := 1.0f
+ frames := 0
+}
+
update :: (dt: f32) {
- fps_timer -= dt;
- frames += 1;
- if fps_timer < 0 {
- fps = frames;
- frames = 0;
- fps_timer = 1.0f;
+
+ #if DEBUG { // Frame counting
+ fps_timer -= dt;
+ frames += 1;
+ if fps_timer < 0 {
+ fps = frames;
+ frames = 0;
+ fps_timer = 1.0f;
+ }
}
}
gl.clearColor(0.1, 0.1, 0.1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
- fps_buffer : [16] u8;
- fps_str := conv.str_format("FPS: %i", ~~ fps_buffer, fps);
- draw_text(fps_str, 0, 0, 32, .{0,1,0});
+ #if false {
+ ui.draw_text("Hello World", 100, 100, 128);
+ ui.draw_text("something else...", 100, 230, 32, .{1,0,0});
- draw_text("Hello World", 100, 100, 128);
- draw_text("something else...", 100, 230, 32, .{1,0,0});
+ ui.draw_text("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 100, 300, 16);
+ ui.draw_text("abcdefghijklmnopqrstuvwxyz", 100, 340, 16);
- draw_text("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 100, 300, 16);
- draw_text("abcdefghijklmnopqrstuvwxyz", 100, 340, 16);
+ gfx.set_texture();
+ gfx.rect(.{100, 400}, .{200, 200}, .{0, 0, 1});
+ }
- gfx.flush();
-}
+ master_rectangle := ui.Rectangle.{ x1 = ~~window_width, y1 = ~~window_height };
+ left, right := ui.Flow.split_vertical(master_rectangle, left_percent=0.4);
+ right_top, right_bottom := ui.Flow.split_horizontal(right, top_height=200);
+ ui.draw_rect(left, .{ 0.5, 0, 0.5 });
+ ui.draw_rect(right, .{ 0, 0.25, 0.5 });
+ ui.draw_rect(right_top, .{ 1, 0, 0 });
+ ui.draw_text("Something here", right_bottom.x0, right_bottom.y0, 48, .{ 1, 1, 1 });
+ #if DEBUG {
+ fps_buffer : [16] u8;
+ fps_str := conv.str_format("FPS: %i", ~~ fps_buffer, fps);
+ ui.draw_text(fps_str, 0, 0, 32, .{0,1,0});
+ }
-draw_text :: (text: str, x: f32, y: f32, size := 32.0f, color := gfx.Color4.{1,1,1}) {
+ gfx.flush();
+}
- gl.bindTexture(gl.TEXTURE_2D, font_texture);
- gfx.set_texture(0);
- for char: text {
- glyph := font->get_glyph(char);
-
- if glyph == null {
- glyph = font->get_glyph(255);
- assert(glyph != null, "NO NULL GLYPH");
- }
- gfx.textured_rect(
- .{ x, y },
- .{ glyph.w * size * font.em, glyph.h * size * font.em },
- .{ glyph.x0, glyph.y0 },
- .{ glyph.x1 - glyph.x0, glyph.y1 - glyph.y0 },
- color = color);
- x += glyph.w * size * 16;
- }
-
- gfx.flush();
- gl.bindTexture(gl.TEXTURE_2D, -1);
-}
--- /dev/null
+package ui
+
+#private_file gfx :: package immediate_mode
+#private_file bitmap_font :: package bitmap_font
+#private_file gl :: package gl
+#private_file math :: package core.math
+
+#private font : bitmap_font.Bitmap_Font;
+#private font_texture : gl.GLTexture;
+
+@Temporary
+DEFAULT_TEXT_SIZE :: 32.0f
+
+
+init_ui :: () {
+ init_font();
+}
+
+#private init_font :: () {
+ font_data := #file_contents "./../res/font_2.data";
+
+ bft := bitmap_font.Bitmap_Font_Texture.{
+ data = font_data,
+ width = 256,
+ height = 256,
+ };
+
+ font = bitmap_font.bitmap_font_create(bft, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \xff:");
+
+ font_texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, font_texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, font_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);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.bindTexture(gl.TEXTURE_2D, -1);
+}
+
+get_text_width :: (text: str, size: f32 = DEFAULT_TEXT_SIZE) -> f32 {
+ return font->get_width(text, size);
+}
+
+// 'x' and 'y' are the top-left coordinates of the text. 'y' is NOT the baseline.
+draw_text :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) {
+ gl.bindTexture(gl.TEXTURE_2D, font_texture);
+ gfx.set_texture(0);
+
+ for char: text {
+ glyph := font->get_glyph(char);
+
+ if glyph == null {
+ glyph = font->get_glyph(255);
+ assert(glyph != null, "NO NULL GLYPH");
+ }
+
+ gfx.textured_rect(
+ .{ x, y },
+ .{ glyph.w * size * font.em, glyph.h * size * font.em },
+ .{ glyph.x0, glyph.y0 },
+ .{ glyph.x1 - glyph.x0, glyph.y1 - glyph.y0 },
+ color = color);
+
+ x += glyph.w * size * font.em;
+ }
+
+ gfx.flush();
+ gl.bindTexture(gl.TEXTURE_2D, -1);
+}
+
+draw_rect :: proc {
+ (use r: Rectangle, color := gfx.Color4.{1,1,1}) {
+ gfx.set_texture();
+
+ width, height := Rectangle.dimensions(r);
+ gfx.rect(.{ x0, y0 }, .{ width, height }, color);
+ },
+
+ (x: f32, y: f32, w: f32, h: f32, color := gfx.Color4.{1,1,1}) {
+ gfx.set_texture();
+ gfx.rect(.{ x, y }, .{ w, h }, color);
+ }
+}
+
+
+
+Rectangle :: struct {
+ //
+ // x0,y0 ------------+
+ // | |
+ // | |
+ // +------------ x1, y1
+ //
+
+ x0: f32 = 0;
+ y0: f32 = 0;
+ x1: f32 = 0;
+ y1: f32 = 0;
+
+ width :: (use r: Rectangle) -> f32 do return math.abs(x1 - x0);
+ height :: (use r: Rectangle) -> f32 do return math.abs(y1 - y0);
+
+ dimensions :: (use r: Rectangle) -> (width: f32, height: f32) {
+ return math.abs(x1 - x0), math.abs(y1 - y0);
+ }
+
+ top_left :: (use r: Rectangle) -> (x: f32, y: f32) do return math.min(x0, x1), math.min(y0, y1);
+ bottom_right :: (use r: Rectangle) -> (x: f32, y: f32) do return math.max(x0, x1), math.max(y0, y1);
+}
+
+
+
+// UI Flow
+
+Flow :: struct {
+ split_vertical :: proc {
+ (r: Rectangle, left_percent: f32) -> (left: Rectangle, right: Rectangle) {
+ return split_vertical(r, left_width=left_percent * Rectangle.width(r));
+ },
+
+ (r: Rectangle, right_percent: f32) -> (left: Rectangle, right: Rectangle) {
+ return split_vertical(r, right_width=right_percent * Rectangle.width(r));
+ },
+
+ (r: Rectangle, left_width: f32) -> (left: Rectangle, right: Rectangle) {
+ x0, y0 := Rectangle.top_left(r);
+ x1, y1 := Rectangle.bottom_right(r);
+
+ return .{ x0=x0, x1=x0+left_width, y0=y0, y1=y1 },
+ .{ x0=x0+left_width, x1=x1, y0=y0, y1=y1 };
+ },
+
+ (r: Rectangle, right_width: f32) -> (left: Rectangle, right: Rectangle) {
+ x0, y0 := Rectangle.top_left(r);
+ x1, y1 := Rectangle.bottom_right(r);
+
+ return .{ x0=x0, x1=x1-right_width, y0=y0, y1=y1 },
+ .{ x0=x1-right_width, x1=x1, y0=y0, y1=y1 };
+ }
+ }
+
+
+ split_horizontal :: proc {
+ (r: Rectangle, top_percent: f32) -> (top: Rectangle, bottom: Rectangle) {
+ return split_horizontal(r, top_height=top_percent * Rectangle.height(r));
+ },
+
+ (r: Rectangle, bottom_percent: f32) -> (top: Rectangle, bottom: Rectangle) {
+ return split_horizontal(r, bottom_height=bottom_percent * Rectangle.height(r));
+ },
+
+ (r: Rectangle, top_height: f32) -> (top: Rectangle, bottom: Rectangle) {
+ x0, y0 := Rectangle.top_left(r);
+ x1, y1 := Rectangle.bottom_right(r);
+
+ return .{ x0=x0, x1=x1, y0=y0, y1=y0+top_height },
+ .{ x0=x0, x1=x1, y0=y0+top_height, y1=y1 };
+ },
+
+ (r: Rectangle, bottom_height: f32) -> (top: Rectangle, bottom: Rectangle) {
+ x0, y0 := Rectangle.top_left(r);
+ x1, y1 := Rectangle.bottom_right(r);
+
+ return .{ x0=x0, x1=x1, y0=y0, y1=y1-bottom_height },
+ .{ x0=x0, x1=x1, y0=y1-bottom_height, y1=y1 };
+ }
+ }
+}
\ No newline at end of file