factored out rendering library
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 23 Dec 2022 04:46:44 +0000 (22:46 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 23 Dec 2022 04:46:44 +0000 (22:46 -0600)
27 files changed:
.vscode/launch.json
onyx-pkg.ini
run_tree/run.sh
src/build.onyx
src/entity/components/collision_mask.onyx
src/entity/components/patron.onyx
src/entity/editor.onyx
src/entity/items.onyx
src/entity/schematics/player.onyx
src/entity/store.onyx
src/main.onyx
src/ogre/canvas.onyx [deleted file]
src/ogre/colors.onyx [deleted file]
src/ogre/font.onyx [deleted file]
src/ogre/immediate.onyx [deleted file]
src/ogre/input.onyx [deleted file]
src/ogre/mesh.onyx [deleted file]
src/ogre/ogre.onyx [deleted file]
src/ogre/shader.onyx [deleted file]
src/ogre/shaders/font.glsl [deleted file]
src/ogre/shaders/imgui.glsl [deleted file]
src/ogre/texture.onyx [deleted file]
src/ogre/ui.onyx [deleted file]
src/ogre/vecmath.onyx [deleted file]
src/ogre/window.onyx [deleted file]
src/utils/any_utils.onyx [deleted file]
src/utils/misc.onyx [new file with mode: 0644]

index 66ac8cd207b79301aee6cdac5a894f21a9a96d41..37150fbd7a7749ba0f325cee0ae92fcba3aab9c6 100644 (file)
@@ -14,7 +14,7 @@
             "name": "Launch",
             "onyxFiles": ["../src/build"],
             "workingDir": "${workspaceFolder}/run_tree",
-            "stopOnEntry": true
+            "stopOnEntry": false
             // "preLaunchTask": "Build debug game"
         }
     ]
index 9e3d0fc6c2be2ba05c59a3b109d42f7aca341e29..a321e07902adefdaa446e9664432c55dc1c26c4d 100644 (file)
@@ -17,16 +17,14 @@ build_cmd=
 library=
 
 [dependencies]
-git://onyxlang.io/repo/glfw3=0.0.2
-git://onyxlang.io/repo/opengles=0.0.2
 git://onyxlang.io/repo/openal=0.0.2
-git://onyxlang.io/repo/stb_truetype=0.0.2
-git://onyxlang.io/repo/stb_image=0.0.2
+git://onyxlang.io/repo/ogre=0.0.8
 
 [dependency_folders]
+git://onyxlang.io/repo/openal=openal
+git://onyxlang.io/repo/ogre=ogre
 git://onyxlang.io/repo/glfw3=glfw3
 git://onyxlang.io/repo/opengles=opengles
-git://onyxlang.io/repo/openal=openal
 git://onyxlang.io/repo/stb_truetype=stb_truetype
 git://onyxlang.io/repo/stb_image=stb_image
 
index 27fb7ad2668421bdd23f8f90f6e16d3160676706..83d0bb31db8c36361b0cdf4341684dd0ad9437fd 100755 (executable)
@@ -1,9 +1,11 @@
 dest=game.wasm
 
 case "$1" in
-    build) shift; onyx -V -I ../src build -o $dest $@ ;;
+    build) shift; onyx -V --tag -I ../src build -o $dest $@ ;;
     check) shift; onyx check -V -I ../src build  $@ ;;
     run)   onyx-run $dest ;;
     debug) onyx-run --debug $dest ;;
-    *)     onyx run -V -I ../src build $@ ;;
+    *)     onyx run -V --tag -I ../src build $@ ;;
 esac
+
+mv tags ..
\ No newline at end of file
index 9246fe2ef0f628a3873d92313ab40a7445882747..5c2199dba665181005651e1d466a20500554bf90 100644 (file)
@@ -4,7 +4,7 @@ package runtime.vars
 MAJOR_VERSION :: 0
 MINOR_VERSION :: 1
 
-// DEBUG :: true
+DEBUG :: true
 
 
 #if runtime.arch == .X86_64  { #library_path "./lib" }
@@ -20,9 +20,6 @@ MINOR_VERSION :: 1
 #load_all "./sfx"
 #load_all "./utils"
 
-#load "./../lib/opengles/module"
-#load "./../lib/glfw3/module"
 #load "./../lib/openal/module"
-#load "./../lib/stb_truetype/module"
-#load "./../lib/stb_image/module"
-#load_all "./ogre"
+#load "./../lib/ogre/module"
+// #load_all "./ogre"
index b798ca2b9563086a72bba3f7134bf0187b535b9b..acbefb812ae63353d582001f521b467602edeeab 100644 (file)
@@ -58,9 +58,12 @@ CollisionMaskComponent :: struct {
         start_pos  := Vector2i.{ ~~start.x / grid_size, ~~start.y / grid_size };
         target_pos := Vector2i.{ ~~target.x / grid_size, ~~target.y / grid_size };
 
-        stack := array.make(.[ .{ pos=start_pos, g=0.0f, h=0.0f } ]);
+        stack := array.make(.[ .{ pos=start_pos, g=0.0f, f=0.0f } ]);
+        defer delete(^stack);
 
         visited: Map(Vector2i, #type struct{ prev: Vector2i; cost: f32 });
+        defer delete(^visited);
+
         found := false;
 
         while stack.count != 0 {
@@ -87,7 +90,7 @@ CollisionMaskComponent :: struct {
                         if array.contains(stack, #(it.pos == .{tx, ty})) do continue;
 
                         g := cast(f32) (math.abs(dx) + math.abs(dy)) + top.g;
-                        h := cast(f32) (math.abs(tx - start_pos.x) + math.abs(ty - start_pos.y));
+                        h := cast(f32) (math.abs(tx - target_pos.x) + math.abs(ty - target_pos.y)) / 2;
                         f := g + h;
 
                         if visited->has(.{ tx, ty }) {
@@ -97,7 +100,7 @@ CollisionMaskComponent :: struct {
                             }
 
                         } else {
-                            stack << .{ .{tx, ty}, g, h, };
+                            stack << .{ .{tx, ty}, g, f };
                             visited[.{ tx, ty }] = .{ top.pos, f };
                         }
                     }
@@ -105,10 +108,8 @@ CollisionMaskComponent :: struct {
             }
 
             array.sort(stack, (n1, n2) => {
-                f1 := n1.g + n1.h;
-                f2 := n2.g + n2.h;
-                if f1 < f2 do return 1;
-                if f2 < f1 do return -1;
+                if n1.f < n2.f do return 1;
+                if n2.f < n1.f do return -1;
                 return 0;
             });
         }
index 366b0eae5c5ffc76e1f4259829a25bb34caed920..2ec578c248faa46c1931d922b58df41d160e3d10 100644 (file)
@@ -135,7 +135,7 @@ PatronComponent :: struct {
                 }
 
                 if path.count == 0 {
-                    array.clear(^path);
+                    array.free(^path);
                     collision_mask := scene->first_component(CollisionMaskComponent);
                     if !(collision_mask->get_path(entity.pos, target_location, ^path)) {
                         debug_log(.Warning, "No path for patron.");
@@ -154,7 +154,7 @@ PatronComponent :: struct {
                 entity.pos += delta * dt;
 
                 if path_pos >= path.count {
-                    array.clear(^path);
+                    array.free(^path);
 
                     target_entity := scene->get(target);
                     target_location := target_entity.pos;
index 8b980db9271db30695abd5fb71ac023678c7c7a6..71c1c0cd4343121e6146183ea8265083ba679a1e 100644 (file)
@@ -13,6 +13,7 @@ use glfw3
 use ogre
 use ogre.ui
 use runtime {type_info :: info}
+use core.misc {as_any}
 
 Editor_Range        :: struct {min, max: f32;}
 Editor_Disabled     :: struct {}
@@ -403,7 +404,7 @@ editor_draw :: () {
 
         y += 4;
         i := 0;
-        y, i = render_struct_fields(ptr_to_any(entity), i, x, y, w, h);
+        y, i = render_struct_fields(as_any(entity), i, x, y, w, h);
 
         y += 32;
         for^ entry: entity.components.entries {
index dc74117b79c7863d290f0359b0a95dfb8d9b1e03..2ef7baa32e989407371489214c544b98402df54b 100644 (file)
@@ -2,6 +2,7 @@
 use core
 use ogre
 use ogre.ui
+use core.misc {as_any, any_nested_selector}
 
 
 Item :: struct {
@@ -74,7 +75,7 @@ item_store_load_items_from_file :: (use this: ^Item_Store, path: str) {
         string.advance(^line, 1);
         string.strip_whitespace(^line);
 
-        member := get_any_for_member(ptr_to_any(current_item), var_name);
+        member := any_nested_selector(as_any(current_item), var_name);
         if member.data == null {
             debug_log(.Warning, "'{}' is not a valid member of Item on line {}.", var_name, line_number);
             continue;
index 3b06c28b633faa4d8cfa2b09806a2cae0a1dc6cf..d293a2d7839c609e023a32d616d7882218dc52e3 100644 (file)
@@ -4,30 +4,30 @@ use glfw3
 use ogre
 
 Player_Controls :: struct {
-    up       : i32;
-    down     : i32;
-    left     : i32;
-    right    : i32;
-    interact : i32;
-    pick_up  : i32;
+    up       : Keys;
+    down     : Keys;
+    left     : Keys;
+    right    : Keys;
+    interact : Keys;
+    pick_up  : Keys;
 }
 
 player_1_controls :: Player_Controls.{
-    up       = GLFW_KEY_W,
-    down     = GLFW_KEY_S,
-    left     = GLFW_KEY_A,
-    right    = GLFW_KEY_D,
-    interact = GLFW_KEY_F,
-    pick_up  = GLFW_KEY_G,
+    up       = .W,
+    down     = .S,
+    left     = .A,
+    right    = .D,
+    interact = .F,
+    pick_up  = .G,
 }
 
 player_2_controls :: Player_Controls.{
-    up       = GLFW_KEY_UP,
-    down     = GLFW_KEY_DOWN,
-    left     = GLFW_KEY_LEFT,
-    right    = GLFW_KEY_RIGHT,
-    interact = GLFW_KEY_COMMA,
-    pick_up  = GLFW_KEY_PERIOD,
+    up       = .UP,
+    down     = .DOWN,
+    left     = .LEFT,
+    right    = .RIGHT,
+    interact = .COMMA,
+    pick_up  = .PERIOD,
 }
 
 
index 3536c9a27b1d68657b66bcc7d8d364734eb09fb8..ae5edd7312687bc747fd1c1c9d571552a524633b 100644 (file)
@@ -1,5 +1,6 @@
 
 use core
+use core.misc {any_nested_selector}
 
 // Flags to control how a field of a structure is being stored
 // in the level file.
@@ -163,7 +164,7 @@ scene_load_from_file :: (use this: ^Scene, filename: str, reset_scene := true) {
         string.strip_whitespace(^line);
 
         set_member :: macro (ptr: rawptr, type: type_expr) {
-            member := get_any_for_member(any.{ptr, type}, var_name);
+            member := any_nested_selector(any.{ptr, type}, var_name);
             if member.data == null {
                 t_info := cast(^Type_Info_Struct) get_type_info(type);
                 debug_log(.Warning, "'{}' is not a valid member of '{}' on line {}.", var_name, t_info.name, line_number);
index 0ee681ba046bea9126b74c7eda3a73b42f483d36..3ed2e186e4c40f40033f51f0c5fe4fe76139e964 100644 (file)
@@ -48,15 +48,13 @@ update :: (dt: f32) {
 
 draw :: () {
     immediate_clear(.{0.15, 0.15, 0.2});
-    defer ui.ui_end_frame();
-    defer input_post_update();
     defer {
         immediate_flush();
 
         #if DEBUG {
             font_set_color(.{1,1,0});
             font_print(debug_font, 0, 16, "FPS: {}", game_fps);
-            font_print(debug_font, 0, 32, "HEAP: {b16}", alloc.heap.get_watermark());
+            font_print(debug_font, 0, 32, "HEAP: {}KB", (alloc.heap.get_watermark() - alloc.heap.get_freed_size()) / 1024);
             font_print(debug_font, 0, 48, "FREE: {}KB", alloc.heap.get_freed_size() / 1024);
 
 
@@ -64,8 +62,6 @@ draw :: () {
             version_str := conv.format(version_buf, "Version: {}.{}", runtime.vars.MAJOR_VERSION, runtime.vars.MINOR_VERSION);
             font_print(debug_font, ~~window.width - font_get_width(debug_font, version_str), 16, version_str);
         }
-
-        window->swap_buffers();
     }
 
     game_draw();
@@ -83,22 +79,13 @@ draw :: () {
 }
 
 run :: () {
-    last := glfwGetTime();
-    now  := last;
-
     seconds := 0.0;
     frame_count := 0;
 
-    while !(window->should_close()) {
-        window->poll_events();
-
-        now = glfwGetTime();
-        dt := now - last;
-        last = now;
-        dt = math.clamp(dt, 0, 0.5);
-
+    window->main_loop() {
         seconds += dt;
         frame_count += 1;
+
         if seconds >= 1 {
             game_fps = ~~frame_count;
             seconds -= 1;
diff --git a/src/ogre/canvas.onyx b/src/ogre/canvas.onyx
deleted file mode 100644 (file)
index 7e85764..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-package ogre
-
-use core
-use opengles
-
-
-Canvas :: struct {
-    width, height: i32;
-
-    framebuffer: GLint;
-    depth_stencil_buffer: GLint;
-    color_texture: GLint;
-}
-
-canvas_make :: (width, height: i32) -> Canvas {
-    canvas: Canvas;
-    canvas.width = width;
-    canvas.height = height;
-
-    glGenFramebuffers(1, ^canvas.framebuffer);
-    glBindFramebuffer(GL_FRAMEBUFFER, canvas.framebuffer);
-
-    glGenTextures(1, ^canvas.color_texture);
-    glBindTexture(GL_TEXTURE_2D, canvas.color_texture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, null);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, canvas.color_texture, 0);
-
-    glGenRenderbuffers(1, ^canvas.depth_stencil_buffer);
-    glBindRenderbuffer(GL_RENDERBUFFER, canvas.depth_stencil_buffer);
-    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
-    glBindRenderbuffer(GL_RENDERBUFFER, 0);
-    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, canvas.depth_stencil_buffer);
-
-    if glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE {
-        printf("[ERROR] Framebuffer is not complete!\n");
-    }
-
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);  
-    return canvas;
-}
-
-canvas_free :: (use canvas: ^Canvas) {
-    glDeleteFramebuffers(1, ^canvas.framebuffer);
-    glDeleteTextures(1, ^canvas.color_texture);
-    glDeleteRenderbuffers(1, ^canvas.depth_stencil_buffer);
-}
-
-canvas_use :: (use canvas: ^Canvas) {
-    if canvas == null {
-        glBindFramebuffer(GL_FRAMEBUFFER, 0);
-        update_view_matrix(global_window.width, global_window.height);
-    } else {
-        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
-        update_view_matrix(width, height);
-    }
-}
-
-canvas_to_texture :: (canvas: ^Canvas) => Texture.{ canvas.color_texture, canvas.width, canvas.height, 3, "<canvas>" };
-
diff --git a/src/ogre/colors.onyx b/src/ogre/colors.onyx
deleted file mode 100644 (file)
index 9a7cceb..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-package ogre
-
-use core
-
-Color :: struct {
-    r, g, b :  f32;
-    a       := 1.0f;
-}
-
-color_to_hsl :: (c: Color) -> (h: f32, s: f32, l: f32) {
-    r := c.r / 255;
-    g := c.g / 255;
-    b := c.b / 255;
-    cmax := math.max(math.max(r, g), b);
-    cmin := math.min(math.min(r, g), b);
-    delta := cmax - cmin;
-
-    h := 0.0f;
-    if cmax == r {
-        m := (g - b) / delta;
-        while m >= 6 do m -= 6;
-        while m < 0  do m += 6;
-        h = 60 * m;
-    }
-    if cmax == g do h = 60 * (b - r) / delta + 2;
-    if cmax == b do h = 60 * (r - g) / delta + 4;
-
-    l := (cmax + cmin) / 2;
-    s := delta / (1 - math.abs(2 * l - 1));
-
-    return h, s, l;
-}
-
-hsl_to_color :: (h, s, l: f32) -> Color {
-    c := (1 - math.abs(2 * l - 1)) * s;
-
-    h_term := h / 60;
-    while h_term < 0  do h_term += 2;
-    while h_term >= 0 do h_term -= 2;
-
-    x := c * (1 - math.abs(h_term - 1));
-    m := l - c / 2;
-
-    r, g, b: f32;
-    if 0   <= h && h < 60  { r = c; g = x; b = 0; }
-    if 60  <= h && h < 120 { r = x; g = c; b = 0; }
-    if 120 <= h && h < 180 { r = 0; g = c; b = x; }
-    if 180 <= h && h < 240 { r = 0; g = x; b = c; }
-    if 240 <= h && h < 300 { r = x; g = 0; b = c; }
-    if 300 <= h && h < 360 { r = c; g = 0; b = x; }
-
-    r = (r + m) * 255;
-    g = (g + m) * 255;
-    b = (b + m) * 255;
-    return .{ r, g, b, 1 };
-}
diff --git a/src/ogre/font.onyx b/src/ogre/font.onyx
deleted file mode 100644 (file)
index 9e95308..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-package ogre
-
-use core
-use stb_truetype
-use opengles
-
-#local {
-    font_registry: Map(FontDescriptor, Font);
-    font_vbo:      GLint;
-    font_vao:      GLint;
-
-    font_shader:   Shader;
-    font_color:    Color;
-}
-
-fonts_init :: () {
-    map.init(^font_registry);
-
-    font_shader = shader_make_from_source(#file_contents "./shaders/font.glsl");
-    shader_use(font_shader);
-
-    glGenVertexArrays(1, ^font_vao);
-    glBindVertexArray(font_vao);
-
-    font_interp_buffer: GLint;
-    glGenBuffers(1, ^font_interp_buffer);
-    glBindBuffer(GL_ARRAY_BUFFER, font_interp_buffer);
-    font_interp_data := f32.[
-        0.0, 0.0,
-        1.0, 0.0,
-        1.0, 1.0,
-        0.0, 1.0,
-    ];
-    glBufferData(GL_ARRAY_BUFFER, sizeof typeof font_interp_data, ~~^font_interp_data, GL_STATIC_DRAW);
-    glEnableVertexAttribArray(0);
-    glVertexAttribPointer(0, 2, GL_FLOAT, false, 2 * sizeof f32, ~~0);
-
-    font_index_buffer: GLint;
-    glGenBuffers(1, ^font_index_buffer);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_index_buffer);
-    font_index_data := u8.[ 0, 1, 2, 0, 2, 3 ];
-    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof typeof font_index_data, ~~^font_index_data, GL_STATIC_DRAW);
-
-    glGenBuffers(1, ^font_vbo);
-    glBindBuffer(GL_ARRAY_BUFFER, font_vbo);
-    glBufferData(GL_ARRAY_BUFFER, 1024 * sizeof stbtt_aligned_quad, null, GL_STREAM_DRAW);
-
-    for 1..5 {
-        glEnableVertexAttribArray(it);
-        glVertexAttribDivisor(it, 1);
-    }
-    glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof stbtt_aligned_quad, ~~ 0);
-    glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof stbtt_aligned_quad, ~~16);
-    glVertexAttribPointer(3, 2, GL_FLOAT, false, sizeof stbtt_aligned_quad, ~~8);
-    glVertexAttribPointer(4, 2, GL_FLOAT, false, sizeof stbtt_aligned_quad, ~~24);
-
-    glBindBuffer(GL_ARRAY_BUFFER, -1);
-    glBindVertexArray(-1);
-
-    font_set_color(.{0,0,0});
-}
-
-
-Font :: struct {
-    texture: GLint;
-    texture_width, texture_height: i32;
-    chars: [] stbtt_packedchar;
-    em: f32;
-}
-
-font_make :: (fd: FontDescriptor) -> Font {
-    texture_size :: 256;
-
-    char_data := memory.make_slice(stbtt_packedchar, 96);
-
-    ttf_file := os.get_contents(fd.path);
-    if ttf_file.count == 0 {
-        println("Bad font");
-        return .{};
-    }
-    defer cfree(ttf_file.data);
-
-    pixels := calloc(texture_size * texture_size);
-    defer cfree(pixels);
-
-    ctx: stbtt_pack_context;
-    stbtt_PackBegin(^ctx, pixels, texture_size, texture_size, 0, 1);
-    stbtt_PackFontRange(^ctx, ttf_file.data, 0, ~~fd.size, #char " ", 96, char_data.data);
-    stbtt_PackEnd(^ctx);
-
-    texture: GLint;
-    glGenTextures(1, ^texture);
-    glBindTexture(GL_TEXTURE_2D, texture);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture_size, texture_size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glBindTexture(GL_TEXTURE_2D, 0);
-
-    font := Font.{
-        texture = texture,
-        texture_width = texture_size,
-        texture_height = texture_size,
-        chars = char_data,
-        em = ~~fd.size,
-    };
-
-    font_registry[fd] = font;
-
-    return font;
-}
-
-font_set_color :: (color: Color) {
-    font_color = color;
-}
-
-font_print :: (font: Font, x, y: f32, format: str, va: ..any) {
-    buf: [1024] u8;
-    msg := conv.format_va(buf, format, va);
-    font_draw(font, x, y, msg);
-}
-
-font_draw :: (font: Font, x, y: f32, msg: str) {
-    quads: ^stbtt_aligned_quad = alloc.from_stack(msg.count * sizeof stbtt_aligned_quad);
-    quad_num := 0;
-
-    x_, y_ := x, y;
-
-    for msg {
-        if it == #char "\n" {
-            x_ = x;
-            y_ += font.em + 2;
-        }
-
-        stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
-            ~~(it - #char " "), ^x_, ^y_, ^quads[quad_num], false);
-
-        quad_num += 1;
-    }
-
-    font_render(font, quads[0 .. quad_num]);
-}
-
-font_draw_centered :: (font: Font, x, y, max_width: f32, msg: str) {
-    quads: ^stbtt_aligned_quad = alloc.from_stack(msg.count * sizeof stbtt_aligned_quad);
-    quad_num := 0;
-
-    width := font_get_width(font, msg);
-    x_, y_ := x, y;
-    x_ = (max_width - width) / 2 + x;
-
-    for msg {
-        if it == #char "\n" {
-            x_ = (max_width - width) / 2 + x;
-            y_ += font.em + 2;
-        }
-
-        stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
-            ~~(it - #char " "), ^x_, ^y_, ^quads[quad_num], false);
-
-        quad_num += 1;
-    }
-
-    font_render(font, quads[0 .. quad_num]);
-}
-
-#local font_render :: (font: Font, quads: [] stbtt_aligned_quad) {
-    // If this is being used in conjunction with the immediate
-    // rendering system, make sure the immediate objects are flushed
-    // before trying to render over them.
-    #if #defined(immediate_flush) {
-        immediate_flush();
-    }
-
-    glBindBuffer(GL_ARRAY_BUFFER, font_vbo);
-    glBufferSubData(GL_ARRAY_BUFFER, 0, quads.count * sizeof stbtt_aligned_quad, quads.data);
-    glBindBuffer(GL_ARRAY_BUFFER, -1);
-
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, font.texture);
-    shader_use(font_shader);
-    shader_set_uniform(font_shader, #cstr "u_texture", 0);
-    shader_set_uniform(font_shader, #cstr "u_color", font_color);
-
-    glDisable(GL_DEPTH_TEST);
-    glBindVertexArray(font_vao);
-    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, ~~0, quads.count);
-    glBindTexture(GL_TEXTURE_2D, -1);
-    glBindVertexArray(-1);
-}
-
-font_get_width :: (font: Font, msg: str) -> f32 {
-    x_, y_ := 0.0f, 0.0f;
-    width := 0.0f;
-
-    quad: stbtt_aligned_quad;
-    for msg {
-        if it == #char "\n" {
-            width = math.max(width, x_);
-            x_ = 0;
-            y_ += font.em + 2;
-            continue;
-        }
-
-        stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
-            ~~(it - #char " "), ^x_, ^y_, ^quad, false);
-    }
-
-    return math.max(x_, width);
-}
-
-font_get_height :: (font: Font, msg: str) -> f32 {
-    x_, y_ := 0.0f, 0.0f;
-    width := 0.0f;
-
-    quad: stbtt_aligned_quad;
-    for msg {
-        if it == #char "\n" {
-            width = math.max(width, x_);
-            x_ = 0;
-            y_ += font.em + 2;
-            continue;
-        }
-
-        stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
-            ~~(it - #char " "), ^x_, ^y_, ^quad, false);
-    }
-
-    return y_ + font.em + 2;
-}
-
-font_get_char_width :: (font: Font, ch: u8) -> f32 {
-    x, y := 0.0f, 0.0f;
-    quad: stbtt_aligned_quad;
-
-    stbtt_GetPackedQuad(font.chars.data, font.texture_width, font.texture_height,
-        ~~(ch - #char " "), ^x, ^y, ^quad, false);
-
-    return x;
-}
-
-
-FontDescriptor :: struct {
-    path : str;
-    size : u32;
-}
-
-#match hash.to_u32 (fd: FontDescriptor) => {
-    name_hash := hash.to_u32(fd.path);
-    size_hash := hash.to_u32(fd.size);
-    return name_hash * 13 + size_hash * 17;
-}
-
-#operator == (f1, f2: FontDescriptor) => f1.path == f2.path && f1.size == f2.size;
-
-font_lookup :: (fd := FontDescriptor.{ "assets/calibri.ttf", 12 }) -> Font {
-    if font_registry->has(fd) {
-        return font_registry[fd];
-    }
-
-    font := font_make(fd);
-    font_registry[fd] = font;
-    return font;
-}
diff --git a/src/ogre/immediate.onyx b/src/ogre/immediate.onyx
deleted file mode 100644 (file)
index 0f37c76..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-package ogre
-
-use core
-use opengles
-use glfw3
-
-immediate_init :: () {
-    memory.alloc_slice(^vertex_data, Maximum_Vertex_Count);
-    vertex_count = 0;
-
-    imgui_shader = shader_make_from_source(#file_contents "./shaders/imgui.glsl");
-    shader_set_uniform(imgui_shader, #cstr "u_texture_enabled", 0.0f);
-    shader_set_uniform(imgui_shader, #cstr "u_texture", 0);
-
-    immediate_mesh = mesh_make(vertex_data, .[], GL_DYNAMIC_DRAW);
-    immediate_color = .{0,0,0};
-}
-
-immediate_flush :: (set_shader := true) {
-    if vertex_count == 0 do return;
-
-    if set_shader {
-        shader_use(imgui_shader);
-        shader_set_uniform(imgui_shader, #cstr "u_texture_enabled", 1.0f if rendering_type == .Image else 0.0f);
-    }
-
-    immediate_mesh.vertex_count = vertex_count;
-    mesh_update_verticies(immediate_mesh, vertex_data);
-
-    mesh_draw(immediate_mesh);
-
-    vertex_count = 0;
-    rendering_type = .Plain;
-    immediate_mesh.primitive = GL_TRIANGLES;
-}
-
-immediate_clear :: (color: Color) {
-    glClearColor(color.r, color.g, color.b, color.a);
-    glClear(GL_COLOR_BUFFER_BIT);
-}
-
-immediate_set_color :: (color: Color) {
-    immediate_color = color;
-}
-
-immediate_vertex :: (x, y: f32, t_x := 0.0f, t_y := 0.0f) {
-    if vertex_count >= Maximum_Vertex_Count do immediate_flush();
-    set_rendering_type(.Plain);
-
-    vertex_data[vertex_count] = .{ .{x, y}, .{t_x, t_y}, immediate_color };
-}
-
-immediate_line :: (x1, y1, x2, y2: f32) {
-    if vertex_count >= Maximum_Vertex_Count do immediate_flush();
-    set_rendering_type(.Line);
-    immediate_mesh.primitive = GL_LINES;
-
-    vertex_data[vertex_count + 0] = .{ .{x1, y1}, .{0, 0}, immediate_color };
-    vertex_data[vertex_count + 1] = .{ .{x2, y2}, .{0, 0}, immediate_color };
-    vertex_count += 2;
-}
-
-immediate_triangle :: (x1, x2, x3: Vector2) {
-    if vertex_count + 3 > Maximum_Vertex_Count do immediate_flush();
-    set_rendering_type(.Plain);
-
-    vertex_data[vertex_count + 0] = .{ x1, .{0,0}, immediate_color };
-    vertex_data[vertex_count + 1] = .{ x2, .{0,0}, immediate_color };
-    vertex_data[vertex_count + 2] = .{ x3, .{0,0}, immediate_color };
-    vertex_count += 3;
-}
-
-immediate_rectangle :: (x, y, w, h: f32) {
-    if vertex_count + 6 > Maximum_Vertex_Count do immediate_flush();
-    set_rendering_type(.Plain);
-
-    vertex_data[vertex_count + 0] = .{ .{x,   y},   .{0,0}, immediate_color };
-    vertex_data[vertex_count + 1] = .{ .{x+w, y},   .{0,0}, immediate_color };
-    vertex_data[vertex_count + 2] = .{ .{x+w, y+h}, .{0,0}, immediate_color };
-    vertex_data[vertex_count + 3] = .{ .{x,   y},   .{0,0}, immediate_color };
-    vertex_data[vertex_count + 4] = .{ .{x+w, y+h}, .{0,0}, immediate_color };
-    vertex_data[vertex_count + 5] = .{ .{x,   y+h}, .{0,0}, immediate_color };
-    vertex_count += 6;
-}
-
-immediate_image :: (image: ^Texture, x, y, w, h: f32) {
-    if vertex_count > 0 do immediate_flush();
-
-    set_rendering_type(.Image);
-    texture_use(image);
-    shader_use(imgui_shader);
-    shader_set_uniform(imgui_shader, #cstr "u_texture", 0);
-
-    vertex_data[vertex_count + 0] = .{ .{x, y},     .{0,0}, immediate_color };
-    vertex_data[vertex_count + 1] = .{ .{x+w, y},   .{1,0}, immediate_color };
-    vertex_data[vertex_count + 2] = .{ .{x+w, y+h}, .{1,1}, immediate_color };
-    vertex_data[vertex_count + 3] = .{ .{x, y},     .{0,0}, immediate_color };
-    vertex_data[vertex_count + 4] = .{ .{x+w, y+h}, .{1,1}, immediate_color };
-    vertex_data[vertex_count + 5] = .{ .{x, y+h},   .{0,1}, immediate_color };
-    vertex_count += 6;
-}
-
-immediate_subimage :: (image: ^Texture, x, y, w, h: f32, tx, ty, tw, th: f32) {
-    if vertex_count > 0 do immediate_flush();
-
-    set_rendering_type(.Image);
-    texture_use(image);
-    shader_use(imgui_shader);
-    shader_set_uniform(imgui_shader, #cstr "u_texture", 0);
-
-    sx := tx / ~~ image.width;
-    sy := ty / ~~ image.height;
-    sw := tw / ~~ image.width;
-    sh := th / ~~ image.height;
-
-    vertex_data[vertex_count + 0] = .{ .{x, y},     .{sx,      sy}, immediate_color };
-    vertex_data[vertex_count + 1] = .{ .{x+w, y},   .{sx+sw,   sy}, immediate_color };
-    vertex_data[vertex_count + 2] = .{ .{x+w, y+h}, .{sx+sw,sy+sh}, immediate_color };
-    vertex_data[vertex_count + 3] = .{ .{x, y},     .{sx,      sy}, immediate_color };
-    vertex_data[vertex_count + 4] = .{ .{x+w, y+h}, .{sx+sw,sy+sh}, immediate_color };
-    vertex_data[vertex_count + 5] = .{ .{x, y+h},   .{sx,   sy+sh}, immediate_color };
-    vertex_count += 6;
-}
-
-immediate_ellipse :: () {}
-
-immediate_push_scissor :: (x, y, w, h: f32) {
-    if vertex_count > 0 do immediate_flush();
-
-    // Assuming that x, y, w, and h are in screen (window) coordinates.
-    x += offset.x;
-    y += offset.y;
-
-    xi := cast(i32) x;
-    yi := cast(i32) y;
-    wi := cast(i32) w;
-    hi := cast(i32) h;
-    scissors << .{xi, yi, wi, hi};
-
-    glEnable(GL_SCISSOR_TEST);
-    glScissor(xi, global_window.height - yi - hi, wi, hi);
-}
-
-immediate_pop_scissor :: () {
-    if scissors.count > 0 {
-        array.pop(^scissors);
-    }
-
-    if scissors.count > 0 {
-        glEnable(GL_SCISSOR_TEST);
-        s := scissors[scissors.count - 1];
-        glScissor(s.x, global_window.height - s.y - s.h, s.w, s.h);
-    } else {
-        glDisable(GL_SCISSOR_TEST);
-    }
-}
-
-immediate_set_scroll :: (scroll_x, scroll_y: f32) {
-    offset = .{ scroll_x, scroll_y };
-    update_model_matrix(offset);
-}
-
-immediate_get_scroll :: () => offset;
-
-Immediate_Vertex :: struct {
-    pos:   Vector2;
-    tex:   Vector2;
-    color: Color;
-}
-
-#local {
-    imgui_shader: Shader;
-
-    Maximum_Vertex_Count :: 1023;
-    vertex_count: i32;
-    vertex_data:  [] Immediate_Vertex;
-
-    immediate_color: Color;
-
-    immediate_mesh: ^Mesh(Immediate_Vertex);
-
-    Rendering_Type :: enum {
-        Plain;
-        Line;
-        Image;
-    }
-    rendering_type := Rendering_Type.Plain;
-
-    Scissor :: struct {
-        x, y, w, h: i32;
-    }
-    scissors: [..] Scissor;
-
-    offset: Vector2;
-
-    set_rendering_type :: (new_type: typeof rendering_type) {
-        if rendering_type != new_type {
-            immediate_flush();
-            rendering_type = new_type;
-        }
-    }
-}
-
-
-
-// @Relocate
-move_towards :: (v: ^$T, target: T, diff: T) {
-    if math.abs(target - *v) <= diff {
-        *v = target;
-        return;
-    }
-
-    if *v < target do *v += diff;
-    if *v > target do *v -= diff;
-}
diff --git a/src/ogre/input.onyx b/src/ogre/input.onyx
deleted file mode 100644 (file)
index 38d656e..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-package ogre
-
-use package core
-use package glfw3
-
-// If you are offseting the mouse coordinate for world space
-// or UI scrolling etc., set this function to be the function
-// to ask for the current offset. Currently scaling the mouse
-// coordinate is not supported, only linear translations.
-Mouse_Offset_Function :: immediate_get_scroll
-
-
-#local {
-    keys_this_frame  : Set(Key_Descriptor)   // Keys currently being pressed this frame
-    keys_last_frame  : Set(Key_Descriptor)   // Keys being pressed in the last frame
-
-    key_codepoints : [..] u32
-
-    buttons_this_frame: [8] bool  // Mouse buttons being pressed this frame
-    buttons_last_frame: [8] bool  // Mouse buttons being pressed last frame
-
-    scroll_x: f64
-    scroll_y: f64
-
-    character_mode := false;
-}
-
-#init () {
-    set.init(^keys_this_frame);
-    set.init(^keys_last_frame);
-}
-
-Key_Descriptor :: struct {
-    key: u32;
-    scancode: u32 = 0;
-    mod: u32      = 0;
-}
-#match hash.to_u32 (use x: Key_Descriptor) => hash.to_u32(key);
-#operator == (x, y: Key_Descriptor) => x.key == y.key;
-
-input_update :: () {
-    glfwGetCursorPos(global_window.glfw_window, ^mouse_x, ^mouse_y);
-}
-
-input_post_update :: () {
-    set.clear(^keys_last_frame);
-    for keys_this_frame.entries do keys_last_frame << it.value;
-
-    for 8 do buttons_last_frame[it] = buttons_this_frame[it];
-
-    last_mouse_x = mouse_x;
-    last_mouse_y = mouse_y;
-    scroll_x = 0;
-    scroll_y = 0;
-
-    array.clear(^key_codepoints);
-}
-
-input_get_chars_this_frame :: () -> [] u32 {
-    return key_codepoints;
-}
-
-input_get_keys_this_frame :: () -> Iterator(Key_Descriptor) {
-    #persist index := 0;
-
-    next :: (_: rawptr) -> (Key_Descriptor, bool) {
-        if index >= keys_this_frame.entries.count do return .{0}, false;
-
-        while keys_last_frame->has(keys_this_frame.entries[index].value) {
-            index += 1;
-            if index >= keys_this_frame.entries.count do return .{0}, false;
-        }
-
-        defer index += 1;
-        return keys_this_frame.entries[index].value, true;
-    }
-
-    index = 0;
-    return .{ null, next };
-}
-
-input_capture_keys :: () {
-    character_mode = true;
-}
-
-input_release_keys :: () {
-    character_mode = false;
-}
-
-is_key_down      :: (key) => !character_mode && set.has(^keys_this_frame, .{key});
-is_key_just_down :: (key) => !character_mode && set.has(^keys_this_frame, .{key}) && !set.has(^keys_last_frame, .{key});
-is_key_just_up   :: (key) => !character_mode && !set.has(^keys_this_frame, .{key}) && set.has(^keys_last_frame, .{key});
-
-is_button_down      :: (button) => buttons_this_frame[button];
-is_button_just_down :: (button) => buttons_this_frame[button] && !buttons_last_frame[button];
-is_button_just_up   :: (button) => !buttons_this_frame[button] && buttons_last_frame[button];
-
-#local {
-    last_mouse_x: f64;
-    last_mouse_y: f64;
-
-    mouse_x: f64;
-    mouse_y: f64;
-}
-
-mouse_get_delta :: () -> (f64, f64) {
-    return mouse_x - last_mouse_x, mouse_y - last_mouse_y;
-}
-
-mouse_get_delta_vector :: () -> Vector2 {
-    dmx, dmy := mouse_get_delta();
-    return .{ ~~dmx, ~~dmy };
-}
-
-mouse_get_position :: () -> (f64, f64) {
-    mx, my := mouse_x, mouse_y;        
-    #if #defined(Mouse_Offset_Function) {
-        scroll := Mouse_Offset_Function();
-        mx -= ~~ scroll.x;
-        my -= ~~ scroll.y;
-    }
-    return mx, my;
-}
-
-mouse_get_position_vector :: () -> Vector2 {
-    mx, my := mouse_x, mouse_y;        
-    #if #defined(Mouse_Offset_Function) {
-        scroll := Mouse_Offset_Function();
-        mx -= ~~ scroll.x;
-        my -= ~~ scroll.y;
-    }
-    return .{ ~~mx, ~~my };
-}
-
-mouse_get_scroll :: () -> (f64, f64) {
-    return scroll_x, scroll_y;
-}
-
-mouse_get_scroll_vector :: () -> Vector2 {
-    return .{ ~~scroll_x, ~~scroll_y };
-}
-
-input_bind_glfw_events :: (window: GLFWwindow_p) {
-    glfwSetKeyCallback(window, #export_name input_key_event);
-    glfwSetCharCallback(window, #export_name input_char_event);
-    glfwSetMouseButtonCallback(window, #export_name input_button_event);
-    glfwSetScrollCallback(window, #export_name input_scroll_event);
-}
-
-#local
-input_button_event :: (window: GLFWwindow_p, button, action, mod: u32) {
-    if action == GLFW_PRESS {
-        buttons_this_frame[button] = true;
-    }
-
-    if action == GLFW_RELEASE {
-        buttons_this_frame[button] = false;
-    }
-}
-
-#local
-input_key_event :: (window: GLFWwindow_p, key, scancode, action, mod: u32) {
-    if action == GLFW_PRESS {
-        keys_this_frame << .{ key, scancode, mod };
-    }
-
-    if action == GLFW_REPEAT {
-        set.remove(^keys_last_frame, .{key});
-    }
-
-    if action == GLFW_RELEASE {
-        set.remove(^keys_this_frame, .{ key });
-    }
-}
-
-#local
-input_char_event :: (window: GLFWwindow_p, codepoint: u32) {
-    if !character_mode do return;
-    key_codepoints << codepoint;       
-}
-
-#local
-input_scroll_event :: (window: GLFWwindow_p, xoff, yoff: f64) {
-    scroll_x = xoff;
-    scroll_y = yoff;
-}
diff --git a/src/ogre/mesh.onyx b/src/ogre/mesh.onyx
deleted file mode 100644 (file)
index ba926aa..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-package ogre
-
-use core
-use opengles
-
-Mesh :: struct (Vertex_Type: type_expr) {
-    handle: GLint;
-    vertex_handle: GLint;
-    index_handle: GLint;
-
-    vertex_count: u32;
-    index_count: u32;
-    primitive: GLuint = GL_TRIANGLES;
-}
-
-mesh_make :: (verticies: [] $T, indicies: [] u32, gl_hint := GL_STATIC_DRAW) -> ^Mesh(T) {
-    mesh := new(Mesh(T));
-    mesh.vertex_count = verticies.count;
-    mesh.index_count  = indicies.count;
-
-    glGenVertexArrays(1, ^mesh.handle);
-    glBindVertexArray(mesh.handle);
-
-    glGenBuffers(1, ^mesh.vertex_handle);
-    glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_handle);
-    glBufferData(GL_ARRAY_BUFFER, sizeof T * verticies.count, verticies.data, gl_hint);
-
-    type_info :: runtime.info
-    vertex_info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(T);
-    vertex_attr := 0;
-    for attr: vertex_info.members {
-        defer vertex_attr += 1;
-        glEnableVertexAttribArray(vertex_attr);
-
-        switch attr.type {
-            case Vector2 do glVertexAttribPointer(vertex_attr, 2, GL_FLOAT, false, sizeof T, ~~attr.offset);
-            case Vector3 do glVertexAttribPointer(vertex_attr, 3, GL_FLOAT, false, sizeof T, ~~attr.offset);
-            case u32 do glVertexAttribIPointer(vertex_attr, 1, GL_UNSIGNED_INT, sizeof T, ~~attr.offset);
-            case i32 do glVertexAttribIPointer(vertex_attr, 1, GL_INT, sizeof T, ~~attr.offset);
-
-            // It would be nice to not have to have all the cases here.
-            // Instead allow for an extensible way of defining them at compile time.
-            case Color do glVertexAttribPointer(vertex_attr, 4, GL_FLOAT, false, sizeof T, ~~attr.offset);
-
-            case #default {
-                buf: [256] u8;
-                msg := conv.str_format(buf, "Unknown type for GL vertex attribute, {}.", attr.type);
-                assert(false, msg);
-            }
-        }
-    }
-
-    if indicies.count > 0 {
-        glGenBuffers(1, ^mesh.index_handle);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_handle);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof i32 * indicies.count, indicies.data, gl_hint);
-    }
-
-    glBindVertexArray(-1);
-
-    return mesh;
-}
-
-mesh_update_verticies :: (use mesh: ^Mesh, verticies: [] mesh.Vertex_Type) {
-    // @TODO // Add bounds checking to arrays here.
-
-    glBindBuffer(GL_ARRAY_BUFFER, vertex_handle);
-    glBufferSubData(GL_ARRAY_BUFFER, 0, verticies.count * sizeof mesh.Vertex_Type, verticies.data);
-    glBindBuffer(GL_ARRAY_BUFFER, -1);
-}
-
-mesh_draw :: (use mesh: ^Mesh) {
-    glBindVertexArray(handle);
-    if index_count > 0 {
-        glDrawElements(primitive, index_count, GL_UNSIGNED_INT, ~~0);
-    } else {
-        glDrawArrays(primitive, 0, vertex_count);
-    }
-    glBindVertexArray(-1);
-}
-
-mesh_free :: (mesh: ^Mesh) {
-    glDeleteBuffers(1, ^mesh.vertex_handle);
-    glDeleteBuffers(1, ^mesh.index_handle);
-    glDeleteVertexArrays(1, ^mesh.handle);
-    cfree(mesh);
-}
-
-
-
diff --git a/src/ogre/ogre.onyx b/src/ogre/ogre.onyx
deleted file mode 100644 (file)
index 4fd1082..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-package ogre
-
-use glfw3 {glfwInit}
-
-ogre_init :: () -> bool {
-    if !glfwInit() {
-        return false;
-    }
-
-    return true;
-}
-
-ogre_setup :: () {
-    shaders_init();
-    fonts_init();
-    immediate_init();
-}
diff --git a/src/ogre/shader.onyx b/src/ogre/shader.onyx
deleted file mode 100644 (file)
index b6bf3fa..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-package ogre
-
-use core
-use opengles
-
-Shader :: struct {
-    vs, fs: GLuint;
-    prog: GLuint;
-}
-
-window_matrix_block_buffer: GLuint;
-world_matrix_block_buffer:  GLuint;
-
-shaders_init :: () {
-    glGenBuffers(1, ^window_matrix_block_buffer);
-    glGenBuffers(1, ^world_matrix_block_buffer);
-
-    glBindBuffer(GL_UNIFORM_BUFFER, window_matrix_block_buffer);
-    glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * 16, null, GL_DYNAMIC_DRAW);
-
-    glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
-    glBufferData(GL_UNIFORM_BUFFER, sizeof f32 * (16 + 16), null, GL_DYNAMIC_DRAW);
-
-    glBindBuffer(GL_UNIFORM_BUFFER, -1);
-
-    glBindBufferBase(GL_UNIFORM_BUFFER, WINDOW_MATRIX_BLOCK, window_matrix_block_buffer);
-    glBindBufferBase(GL_UNIFORM_BUFFER, WORLD_MATRIX_BLOCK, world_matrix_block_buffer);
-}
-
-shader_make :: (shader_path: str) -> Shader {
-    shader_source := os.get_contents(shader_path);
-    return shader_make_from_source(shader_source);
-}
-
-shader_make_from_source :: (shader_source: str) -> Shader {
-    vs := compile_shader(shader_source, GL_VERTEX_SHADER);
-    fs := compile_shader(shader_source, GL_FRAGMENT_SHADER);
-
-    prog := link_program(vs, fs);
-
-    s := Shader.{vs, fs, prog};
-    shader_link_window_matrix_block(s);
-    shader_link_world_matrix_block(s);
-
-    return s;
-}
-
-shader_use :: (shader: Shader) {
-    glUseProgram(shader.prog);
-}
-
-#local {
-    WINDOW_MATRIX_BLOCK :: 0;
-    WORLD_MATRIX_BLOCK  :: 1;
-}
-
-shader_link_window_matrix_block :: (use shader: Shader) {
-    matrix_block_index := glGetUniformBlockIndex(prog, #cstr "u_window_matrix_block");
-    if matrix_block_index == GL_INVALID_INDEX do return;
-
-    glUniformBlockBinding(prog, matrix_block_index, WINDOW_MATRIX_BLOCK);
-}
-
-shader_link_world_matrix_block :: (use shader: Shader) {
-    matrix_block_index := glGetUniformBlockIndex(prog, #cstr "u_world_matrix_block");
-    if matrix_block_index == GL_INVALID_INDEX do return;
-
-    glUniformBlockBinding(prog, matrix_block_index, WORLD_MATRIX_BLOCK);
-}
-
-shader_set_uniform :: (shader: Shader, uniform: cstr, value: $T) {
-    glUseProgram(shader.prog);
-    location := glGetUniformLocation(shader.prog, uniform);
-
-    set_uniform_internal(location, value);
-
-    set_uniform_internal :: #match {
-        macro (location: GLint, value: u32) do glUniform1i(location, value); ,
-        macro (location: GLint, value: f32) do glUniform1f(location, value); ,
-        macro (location: GLint, value: Vector2) do glUniform2f(location, value.x, value.y); ,
-        macro (location: GLint, value: Vector3) do glUniform3f(location, value.x, value.y, value.z); ,
-        macro (location: GLint, value: Color)   do glUniform4f(location, value.r, value.g, value.b, value.a); ,
-
-        macro (location: GLint, value: $T) {
-            buffer: [1024] u8;
-            assert(false, conv.format(buffer, "Bad shader_set_uniform case: {}", T));
-        }
-    }
-}
-
-update_view_matrix :: (width, height: u32) {
-    matrix : [16] f32;
-    top    := 0.0f;
-    left   := 0.0f;
-    right  := cast(f32) width;
-    bottom := cast(f32) height;
-    far    := 10.0f;
-    near   := 0f;
-
-    matrix[0] = 2 / (right - left);
-    matrix[5] = 2 / (top - bottom);
-    matrix[10] = -2 / (far - near);
-    matrix[12] = -(right + left) / (right - left);
-    matrix[13] = -(top + bottom) / (top - bottom);
-    matrix[14] = -(far + near) / (far - near);
-    matrix[15] = 1;
-
-    glBindBuffer(GL_UNIFORM_BUFFER, window_matrix_block_buffer);
-    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof matrix, ^matrix);
-    glBindBuffer(GL_UNIFORM_BUFFER, -1);
-
-    glViewport(0, 0, width, height);
-}
-
-update_world_matrix :: () {
-    world_mat: [16] f32;
-    world_mat[0] = 1;
-    world_mat[5] = 1;
-    world_mat[10] = 1;
-    world_mat[15] = 1;
-
-    glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
-    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof world_mat, ^world_mat);
-    glBindBuffer(GL_UNIFORM_BUFFER, -1);
-}
-
-update_model_matrix :: (v: Vector2) {
-    model_mat: [16] f32;
-    model_mat[0]  = 1;
-    model_mat[5]  = 1;
-    model_mat[10] = 1;
-    model_mat[12] = v.x;
-    model_mat[13] = v.y;
-    model_mat[14] = 0;
-    model_mat[15] = 1;
-
-    glBindBuffer(GL_UNIFORM_BUFFER, world_matrix_block_buffer);
-    glBufferSubData(GL_UNIFORM_BUFFER, 16 * sizeof f32, sizeof typeof model_mat, ^model_mat);
-    glBindBuffer(GL_UNIFORM_BUFFER, -1);
-}
-
-
-#local {
-    compile_shader :: (source: str, type: GLenum) -> GLint {
-        shader := glCreateShader(type);
-
-        #persist VERTEX_HEADER := """
-#version 300 es
-#define VERTEX_SHADER 1
-#define COMM out
-        """;
-
-        #persist FRAGMENT_HEADER := """
-#version 300 es
-#define FRAGMENT_SHADER 1
-#define COMM in
-        """;
-
-        header      := VERTEX_HEADER if type == GL_VERTEX_SHADER else FRAGMENT_HEADER;
-        sources     : [] cptr(u8) = .[ cptr.make(header.data), cptr.make(source.data) ];
-        source_lens : [] i32      = .[ header.count,           source.count ];
-
-        glShaderSource(shader, 2, sources.data, source_lens.data);
-        glCompileShader(shader);
-
-        success: GLint;
-        if glGetShaderiv(shader, GL_COMPILE_STATUS, ^success); success == GL_FALSE {
-            buf_data: [2048] u8;
-            buf := str.{ ~~buf_data, 0 };
-            glGetShaderInfoLog(shader, 2048, ^buf.count, buf.data);
-            println(buf);
-        }
-
-        return shader;
-    }
-
-    link_program :: (vertex_shader, fragment_shader: GLint) -> GLuint {
-        prog := glCreateProgram();
-        glAttachShader(prog, vertex_shader);
-        glAttachShader(prog, fragment_shader);
-        glLinkProgram(prog);
-
-        success: GLint;
-        if glGetProgramiv(prog, GL_LINK_STATUS, ^success); success == GL_FALSE {
-            buf_data: [1024] u8;
-            buf := str.{ ~~buf_data, 0 };
-            glGetProgramInfoLog(prog, 1024, ^buf.count, buf.data);
-            println(buf);
-        }
-
-        return prog;
-    }
-}
diff --git a/src/ogre/shaders/font.glsl b/src/ogre/shaders/font.glsl
deleted file mode 100644 (file)
index 8fdf5c9..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-precision mediump float;
-
-COMM vec2 v_texture;
-
-#ifdef VERTEX_SHADER
-
-layout(location = 0) in vec2 a_interp;
-layout(location = 1) in vec2 a_pos_top_left;
-layout(location = 2) in vec2 a_pos_bottom_right;
-layout(location = 3) in vec2 a_tex_top_left;
-layout(location = 4) in vec2 a_tex_bottom_right;
-
-layout(std140) uniform u_window_matrix_block {
-    mat4 u_window;
-};
-
-layout(std140) uniform u_world_matrix_block {
-    mat4 u_world;
-    mat4 u_model;
-};
-
-void main() {
-    gl_Position = u_window * u_world * u_model * vec4(mix(a_pos_top_left, a_pos_bottom_right, a_interp), 0, 1);
-    v_texture = mix(a_tex_top_left, a_tex_bottom_right, a_interp);
-}
-
-#endif
-
-#ifdef FRAGMENT_SHADER
-
-uniform sampler2D u_texture;
-uniform vec4      u_color;
-
-out vec4 fragColor;
-
-void main() {
-    fragColor = vec4(u_color.rgb, u_color.a * texture(u_texture, v_texture).a);
-}
-
-#endif
diff --git a/src/ogre/shaders/imgui.glsl b/src/ogre/shaders/imgui.glsl
deleted file mode 100644 (file)
index 26c0260..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-precision mediump float;
-
-COMM vec4 v_col;
-COMM vec2 v_tex;
-
-#ifdef VERTEX_SHADER
-
-layout(location = 0) in vec2 a_pos;
-layout(location = 1) in vec2 a_tex;
-layout(location = 2) in vec4 a_col;
-
-layout(std140) uniform u_window_matrix_block {
-    mat4 u_window;
-};
-
-layout(std140) uniform u_world_matrix_block {
-    mat4 u_world;
-    mat4 u_model;
-};
-
-void main() {
-    gl_Position = u_window * u_world * u_model * vec4(a_pos, 0, 1);
-    v_tex = a_tex;
-    v_col = a_col;
-}
-
-#endif
-
-#ifdef FRAGMENT_SHADER
-
-uniform sampler2D u_texture;
-uniform float u_texture_enabled;
-
-out vec4 fragColor;
-
-void main() {
-    fragColor = v_col * mix(vec4(1), texture(u_texture, v_tex), vec4(u_texture_enabled));
-}
-
-#endif
diff --git a/src/ogre/texture.onyx b/src/ogre/texture.onyx
deleted file mode 100644 (file)
index dbf3157..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-package ogre
-
-use core
-use opengles
-use stb_image
-
-#local texture_cache: Map(str, Texture);
-
-Texture :: struct {
-    texture: GLint;
-    width, height, channels: i32;
-    filename: str;
-}
-
-texture_lookup :: #match #local {}
-
-#overload
-texture_lookup :: (filename: str) -> (Texture, bool) {
-    if texture_cache->has(filename) {
-        return texture_cache[filename], true;
-    }
-
-    buffer: [512] u8;
-    memory.copy(~~ buffer, filename.data, math.min(filename.count, 511));
-    return texture_lookup(cast(cstr) buffer);
-}
-
-#overload
-texture_lookup :: (path: cstr) -> (Texture, bool) {
-    filename := string.from_cstr(path);
-    if texture_cache->has(filename) {
-        return texture_cache[filename], true;
-    }
-
-    tex: Texture;
-    tex.filename = filename;
-    pixels := stbi_load(path, ^tex.width, ^tex.height, ^tex.channels, 4);
-    if pixels == null {
-        printf("[WARN ] Failed to load texture: {}\n", filename);
-        return .{}, false;
-    }
-    defer stbi_image_free(pixels);
-
-    glGenTextures(1, ^tex.texture);
-    glBindTexture(GL_TEXTURE_2D, tex.texture);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width, tex.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
-    // Are these sensible defaults?
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-    glBindTexture(GL_TEXTURE_2D, 0);
-
-    // This assumes that the filename data is going to be persistant forever.
-    // Not a great assumption to make but is it really worth copying it?
-    texture_cache[filename] = tex;
-    printf("[INFO ] Loaded texture: {}\n", filename);
-    return tex, true;
-}
-
-texture_free :: (use tex: ^Texture) {
-    glDeleteTextures(1, ^texture);
-}
-
-texture_use :: (use tex: ^Texture, texture_binding := 0) {
-    glActiveTexture(GL_TEXTURE0 + texture_binding);
-    glBindTexture(GL_TEXTURE_2D, texture);
-}
-
-
-Texture_Wrap :: enum {
-    Clamp :: GL_CLAMP_TO_EDGE | 0;
-    Repeat :: GL_REPEAT | 0;
-    Mirrored_Repeat :: GL_MIRRORED_REPEAT | 0;
-}
-
-texture_wrap :: (use tex: ^Texture, wrap: Texture_Wrap) {
-    glBindTexture(GL_TEXTURE_2D, texture);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ~~ wrap);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ~~ wrap);
-}
-
-texture_cache_clear :: () {
-    for^ texture_cache.entries {
-        glDeleteTextures(1, ^it.value.texture);
-    }
-
-    map.clear(^texture_cache);
-}
diff --git a/src/ogre/ui.onyx b/src/ogre/ui.onyx
deleted file mode 100644 (file)
index 1242f11..0000000
+++ /dev/null
@@ -1,731 +0,0 @@
-package ogre.ui
-
-//
-// Very simple immediate mode UI
-//
-
-use core
-use opengles
-use glfw3
-use ogre
-
-UI_Id :: u32
-
-ui_end_frame :: () {
-    hot_item_depth_needed = hot_item_depth;
-    if !hot_item_was_set do set_hot_item(0);
-    hot_item_depth = 0;
-    hot_item_was_set = false;
-
-    for^ animation_states.entries {
-        if !it.value.accessed_this_frame || (it.value.click_time == 0 && it.value.hover_time == 0)  {
-            map.delete(^animation_states, it.key);
-        }
-    }
-
-    for^ animation_states.entries {
-        it.value.accessed_this_frame = false;
-    }
-
-    if active_countdown > 0 {
-        active_countdown -= 1;
-        if active_countdown == 0 {
-            set_active_item(0);
-            input_release_keys();
-        }
-    }
-}
-
-//
-// Buttons
-//
-Button_Theme :: struct {
-    use text_theme := Text_Theme.{};
-    use animation_theme := Animation_Theme.{};
-
-    background_color := Color.{ 0.1, 0.1, 0.1 };
-    hover_color      := Color.{ 0.3, 0.3, 0.3 };
-    click_color      := Color.{ 0.5, 0.5, 0.7 };
-
-    border_color := Color.{0.2, 0.2, 0.2};
-    border_width := 2.0f;
-
-    active := false;
-}
-
-#local default_button_theme := Button_Theme.{};
-
-draw_button  :: (use r: Rect, text: str, theme := ^default_button_theme, site := #callsite, increment := 0) -> bool {
-    result := false;
-
-    hash := get_site_hash(site, increment);
-    animation_state := get_animation(hash);
-    mx, my := mouse_get_position();
-
-    contains := Rect.contains(r, .{~~mx, ~~my});
-
-    if is_active_item(hash) {
-        renew_active_item(hash);
-        if is_button_just_up(GLFW_MOUSE_BUTTON_LEFT) {
-            if is_hot_item(hash) && contains {
-                result = true;
-                animation_state.click_time = 1.0f;
-            }
-
-            set_active_item(0);
-        }
-    } elseif is_hot_item(hash) {
-        if is_button_down(GLFW_MOUSE_BUTTON_LEFT) {
-            set_active_item(hash);
-        }
-    }
-
-    if contains {
-        set_hot_item(hash);
-    }
-
-    if is_hot_item(hash) || theme.active {
-        move_towards(^animation_state.hover_time, 1.0f, theme.hover_speed);
-    } else {
-        move_towards(^animation_state.hover_time, 0.0f, theme.hover_speed);
-    }
-
-    border_width := theme.border_width;
-
-    immediate_set_color(theme.border_color);
-    immediate_rectangle(x, y, w, h);
-
-    surface_color := color_lerp(animation_state.hover_time, theme.background_color, theme.hover_color);
-    surface_color  = color_lerp(animation_state.click_time, surface_color, theme.click_color);
-    immediate_set_color(surface_color);
-    immediate_rectangle(x + border_width, y + border_width, w - border_width * 2, h - border_width * 2);
-
-    font := font_lookup(.{theme.font_name, theme.font_size});
-    font_height := font_get_height(font, text);
-    font_set_color(theme.text_color);
-    font_draw_centered(font, x, y + (h - font_height) / 2 + font.em - 2, w, text);
-
-    move_towards(^animation_state.click_time, 0.0f, theme.click_decay_speed);
-
-    return result;
-}
-
-
-//
-// Sliders
-//
-Slider_Theme :: struct {
-    use text_theme := Text_Theme.{};
-    use animation_theme := Animation_Theme.{};
-
-    box_color        := Color.{ 0.1, 0.1, 0.1 };
-    box_border_color := Color.{ 0.2, 0.2, 0.2 };
-    box_border_width := 4.0f;   // @InPixels
-
-    bar_color                := Color.{ 0.4, 0.4, 0.4 };
-    bar_hover_color          := Color.{ 0, 0, 1 };
-    bar_hover_negative_color := Color.{ 1, 0, 0 }; // The color when value is less than 0
-}
-
-#local default_slider_theme := Slider_Theme.{};
-
-draw_slider :: (use r: Rect, value: ^$T, min_value: T, max_value: T, theme := ^default_slider_theme, site := #callsite, increment := 0) -> bool {
-    result := false;
-
-    hash := get_site_hash(site, increment);
-    state := get_animation(hash);
-    mx, my := mouse_get_position();
-
-    if is_hot_item(hash) {
-        if is_button_down(GLFW_MOUSE_BUTTON_LEFT) {
-            set_active_item(hash);
-            result = true;
-
-            // Animate this?
-            sx := ~~mx - x;
-
-            if T == i32 || T == i64 || T == u32 || T == u64 {
-                step_width := w / ~~math.abs(max_value - min_value);
-                percent := (sx + step_width / 2) / w;
-                *value = math.lerp(percent, min_value, max_value);
-                *value = math.clamp(*value, min_value, max_value);
-
-            } else {
-                percent := sx / w;
-                *value = math.lerp(percent, min_value, max_value);
-                *value = math.clamp(*value, min_value, max_value);
-            }
-        } else {
-            set_active_item(0);
-        }
-    }
-
-    if Rect.contains(r, .{ ~~mx, ~~my }) {
-        set_hot_item(hash);
-    }
-
-    if is_hot_item(hash) {
-        move_towards(^state.hover_time, 1.0f, theme.hover_speed);
-    } else {
-        move_towards(^state.hover_time, 0.0f, theme.hover_speed);
-    }
-
-    box_border_width := theme.box_border_width;
-
-    bar_color := theme.bar_color;
-    if *value < 0 do bar_color = color_lerp(state.hover_time, bar_color, theme.bar_hover_negative_color);
-    else          do bar_color = color_lerp(state.hover_time, bar_color, theme.bar_hover_color);
-
-    immediate_set_color(theme.box_border_color);
-    immediate_rectangle(x, y, w, h);
-
-    immediate_set_color(theme.box_border_color);
-    immediate_rectangle(x + box_border_width, y + box_border_width, w - box_border_width * 2, h - box_border_width * 2);
-
-    box_width := cast(f32) (*value - min_value) / ~~(max_value - min_value);
-    box_width *= w - box_border_width * 2;
-    box_width = math.clamp(box_width, 0, w - box_border_width * 2);
-    immediate_set_color(bar_color);
-    immediate_rectangle(x + box_border_width, y + box_border_width, box_width, h - box_border_width * 2);
-
-    return result;
-}
-
-//
-// Textbox
-//
-Textbox_Theme :: struct {
-    use text_theme := Text_Theme.{
-        text_color = .{ 0, 0, 0 }
-    };
-
-    use animation_theme := Animation_Theme.{};
-
-    background_color := Color.{ 0.8, 0.8, 0.8 };
-    hover_color      := Color.{ 1.0, 1.0, 1.0 };
-    click_color      := Color.{ 0.5, 0.5, 0.7 };
-
-    border_color := Color.{ 0.2, 0.2, 0.2 };
-    border_width := 6.0f;   // @InPixels
-
-    cursor_color := Color.{ 0.5, 0.5, 0.5 };
-    cursor_width := 4.0f;   // @InPixels
-    cursor_blink_speed := 0.04f;   // Bigger is faster
-
-    placeholder_text_color := Color.{ 0.5, 0.5, 0.5 };
-}
-
-#local {
-    default_textbox_theme := Textbox_Theme.{};
-
-    Textbox_Editing_State :: struct {
-        hash: UI_Id = 0;
-
-        cursor_position: i32 = 0;
-        cursor_animation := 0.0f;
-        cursor_animation_speed := 0.02f;
-
-        // @HACK // Otherwise the action keys are evaluated every frame.
-        action_key_timeout := 0.0f;
-    }
-
-    textbox_editing_state := Textbox_Editing_State.{};
-}
-
-draw_textbox :: (use r: Rect, text_buffer: ^[..] u8, placeholder := null_str, theme := ^default_textbox_theme, site := #callsite, increment := 0) -> bool {
-    result := false;
-
-    hash := get_site_hash(site, increment);
-    animation_state := get_animation(hash);
-    mx, my := mouse_get_position();
-
-    border_width := theme.border_width;
-    text_color := theme.text_color;
-    text := str.{text_buffer.data, text_buffer.count};
-    if text.count == 0 && placeholder.count > 0 {
-        text = placeholder;
-        text_color = theme.placeholder_text_color;
-    }
-
-    font := font_lookup(.{theme.font_name, theme.font_size});
-    text_width  := font_get_width(font, text);
-    text_height := font_get_height(font, text);
-
-    text_x := x + border_width;
-    text_y := y + font.em + (h - text_height) / 2;
-
-    contains := Rect.contains(r, .{~~mx, ~~my});
-
-    if is_hot_item(hash) && !is_active_item(hash) {
-        if is_button_down(GLFW_MOUSE_BUTTON_LEFT) && contains {
-            set_active_item(hash);
-            input_capture_keys();
-            textbox_editing_state.hash = hash;
-            textbox_editing_state.cursor_animation_speed = theme.cursor_blink_speed;
-        }
-    }
-
-    if is_active_item(hash) {
-        renew_active_item(hash);
-        if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) && !contains {
-            set_active_item(0);
-            input_release_keys();
-            textbox_editing_state.hash = 0;
-            textbox_editing_state.cursor_position = 0;
-        }
-    }
-
-    if contains {
-        set_hot_item(hash);
-    }
-
-    if textbox_editing_state.hash == hash {
-        move_towards(^textbox_editing_state.cursor_animation, 0.0f, textbox_editing_state.cursor_animation_speed);
-        if textbox_editing_state.cursor_animation <= 0.0f do textbox_editing_state.cursor_animation = 1.0f;
-
-        if is_button_down(GLFW_MOUSE_BUTTON_LEFT) && contains {
-            textbox_editing_state.cursor_animation = 1.0f;
-            textbox_editing_state.cursor_position = screen_to_cursor(^font, text_x, text_y, text, ~~mx, ~~my);
-        }
-
-        for key: input_get_keys_this_frame() {
-            switch key.key {
-                case GLFW_KEY_ESCAPE {
-                    set_active_item(0);
-                    input_release_keys();
-                }
-
-                case GLFW_KEY_LEFT  do textbox_editing_state.cursor_position -= 1;
-                case GLFW_KEY_RIGHT do textbox_editing_state.cursor_position += 1;
-                case GLFW_KEY_END   do textbox_editing_state.cursor_position = text_buffer.count;
-                case GLFW_KEY_HOME  do textbox_editing_state.cursor_position = 0;
-
-                case GLFW_KEY_BACKSPACE {
-                    if textbox_editing_state.cursor_position > 0 {
-                        array.delete(text_buffer, textbox_editing_state.cursor_position - 1);
-                    }
-                    textbox_editing_state.cursor_position = math.max(~~0, textbox_editing_state.cursor_position - 1);
-                }
-
-                case GLFW_KEY_DELETE {
-                    array.delete(text_buffer, textbox_editing_state.cursor_position);
-                }
-            }
-        }
-
-        for ch: input_get_chars_this_frame() {
-            array.insert(text_buffer, textbox_editing_state.cursor_position, ~~ch);
-            textbox_editing_state.cursor_position += 1;
-            result = true;
-        }
-
-        textbox_editing_state.cursor_position = math.clamp(textbox_editing_state.cursor_position, 0, text_buffer.count);
-        textbox_editing_state.cursor_animation = 1.0f;
-
-        text = str.{text_buffer.data, text_buffer.count};
-    }
-
-    if is_hot_item(hash) {
-        move_towards(^animation_state.hover_time, 1.0f, theme.hover_speed);
-    } else {
-        move_towards(^animation_state.hover_time, 0.0f, theme.hover_speed);
-    }
-
-    immediate_push_scissor(x, y, w, h);
-    immediate_set_color(theme.border_color);
-    immediate_rectangle(x, y, w, h);
-
-    surface_color := color_lerp(animation_state.hover_time, theme.background_color, theme.hover_color);
-    surface_color  = color_lerp(animation_state.click_time, surface_color, theme.click_color);
-    immediate_set_color(surface_color);
-    immediate_rectangle(x + border_width, y + border_width, w - border_width * 2, h - border_width * 2);
-
-    // Draw the cursor on textboxes
-    if is_active_item(hash) {
-        cursor := cursor_to_screen(^font, x + border_width, y + border_width, text, textbox_editing_state.cursor_position);
-        right_edge := x + w - border_width * 2;
-        if cursor.x > right_edge {
-            text_x -= cursor.x - right_edge;
-            cursor.x = right_edge - 2;
-        }
-        immediate_set_color(.{0,0,0});
-        immediate_rectangle(cursor.x, cursor.y + 2, 2, h - border_width * 2 - 4);
-    }
-
-    font_set_color(theme.text_color);
-    font_draw(font, text_x, text_y, text); // This is technically a frame late for updating the text?
-
-    move_towards(^animation_state.click_time, 0.0f, theme.click_decay_speed);
-
-    immediate_pop_scissor();
-    return result;
-
-    cursor_to_screen :: (font: ^Font, x, y: f32, text: str, cur_pos: i32) -> Vector2 {
-        cx := x;
-        cy := y;
-
-        for text[0 .. cur_pos] {
-            if it == #char "\n" {
-                cx = 0;
-                cy += font.em + 2;
-            } else {
-                cx += font_get_char_width(*font, it);
-            }
-        }
-
-        return .{ cx, cy };
-    }
-
-    screen_to_cursor :: (font: ^Font, x, y: f32, text: str, mouse_x, mouse_y: f32) -> i32 {
-        mx := mouse_x - x;
-        my := mouse_y - y;
-        
-        cx := 0.0f; 
-        cy := 0.0f;
-        for pos: text.count {
-            if text[pos] == #char "\n" {
-                cx = 0;
-                cy += font.em + 2;
-            } else {
-                cx += font_get_char_width(*font, text[pos]);
-            }
-
-            if cy >= my && cx >= mx {
-                return pos;
-            }
-        }
-
-        return text.count;
-    }
-}
-
-
-
-
-//
-// Checkboxes
-//
-Checkbox_Theme :: struct {
-    use text_theme := Text_Theme.{};
-    use animation_theme := Animation_Theme.{};
-
-    box_color        := Color.{ 0.2, 0.2, 0.2 };
-    box_border_width := 4.0f;    // @InPixels
-    box_size         := 20.0f;   // @InPixels
-
-    checked_color       := Color.{ 1, 0, 0 };
-    checked_hover_color := Color.{ 1, 0.6, 0.6 };
-
-    background_color := Color.{ 0.05, 0.05, 0.05 };  // Background of the checkbox button.
-    hover_color      := Color.{ 0.3, 0.3, 0.3 };
-    click_color      := Color.{ 0.5, 0.5, 0.7 };
-}
-
-#local default_checkbox_theme := Checkbox_Theme.{};
-
-draw_checkbox :: (use r: Rect, value: ^bool, text: str, theme := ^default_checkbox_theme, site := #callsite, increment := 0) -> bool {
-    result := false;
-
-    hash := get_site_hash(site, increment);
-    animation_state := get_animation(hash);
-    mx, my := mouse_get_position();
-
-    contains := Rect.contains(r, .{~~mx, ~~my});
-
-    if is_active_item(hash) {
-        renew_active_item(hash);
-        if is_button_just_up(GLFW_MOUSE_BUTTON_LEFT) {
-            if is_hot_item(hash) && contains {
-                result = true;
-                *value = !*value;
-                animation_state.click_time = 1.0f;
-            }
-
-            set_active_item(0);
-        }
-    } elseif is_hot_item(hash) {
-        if is_button_down(GLFW_MOUSE_BUTTON_LEFT) {
-            set_active_item(hash);
-        }
-    }
-
-    if contains {
-        set_hot_item(hash);
-    }
-
-    if is_hot_item(hash) {
-        move_towards(^animation_state.hover_time, 1.0f, theme.hover_speed);
-    } else {
-        move_towards(^animation_state.hover_time, 0.0f, theme.hover_speed);
-    }
-
-    box_border_width := theme.box_border_width;
-    box_size         := theme.box_size;
-
-    immediate_set_color(theme.box_color);
-    immediate_rectangle(x + 4, y + (h - box_size) / 2, box_size, box_size);
-
-    surface_color : Color;
-    if *value {
-        surface_color = theme.checked_color;
-        surface_color = color_lerp(animation_state.hover_time, surface_color, theme.checked_hover_color);
-
-    } else {
-        surface_color = theme.background_color;
-        surface_color = color_lerp(animation_state.hover_time, surface_color, theme.hover_color);
-    }
-
-    surface_color = color_lerp(animation_state.click_time, surface_color, theme.click_color);
-
-    immediate_set_color(surface_color);
-    immediate_rectangle(x + 4 + box_border_width, y + (h - box_size) / 2 + box_border_width, box_size - box_border_width * 2, box_size - box_border_width * 2);
-
-    font := font_lookup(.{theme.font_name, theme.font_size});
-    text_width  := font_get_width(font, text);
-    text_height := font_get_height(font, text);
-
-    font_set_color(theme.text_color);
-    font_draw(font, x + box_size + 4 * 2, y + font.em + (h - text_height) / 2, text);
-
-    move_towards(^animation_state.click_time, 0.0f, theme.click_decay_speed);
-
-    return result;
-}
-
-
-//
-// Radio buttons
-//
-Radio_Theme :: struct {
-    use text_theme := Text_Theme.{};
-    use animation_theme := Animation_Theme.{};
-
-    box_color        := Color.{ 0.2, 0.2, 0.2 };
-    box_border_width := 4.0f;    // @InPixels
-    box_size         := 20.0f;   // @InPixels
-
-    checked_color       := Color.{ 0, 0, 1 };
-    checked_hover_color := Color.{ 0.6, 0.6, 1 };
-
-    background_color := Color.{ 0.05, 0.05, 0.05 };  // Background of the checkbox button.
-    hover_color      := Color.{ 0.3, 0.3, 0.3 };
-    click_color      := Color.{ 0.5, 0.5, 0.7 };
-}
-
-#local default_radio_theme := Radio_Theme.{};
-
-draw_radio :: (use r: Rect, value: ^$T, set_to: T, text: str, theme := ^default_radio_theme, site := #callsite, increment := 0) -> bool {
-    result := false;
-
-    hash := get_site_hash(site, increment);
-    animation_state := get_animation(hash);
-    mx, my := mouse_get_position();
-
-    contains := Rect.contains(r, .{~~mx, ~~my});
-
-    if is_active_item(hash) {
-        renew_active_item(hash);
-        if is_button_just_up(GLFW_MOUSE_BUTTON_LEFT) {
-            if is_hot_item(hash) && contains {
-                result = true;
-                *value = set_to;
-                animation_state.click_time = 1.0f;
-            }
-
-            set_active_item(0);
-        }
-    } elseif is_hot_item(hash) {
-        if is_button_down(GLFW_MOUSE_BUTTON_LEFT) {
-            set_active_item(hash);
-        }
-    }
-
-    if contains {
-        set_hot_item(hash);
-    }
-
-    if is_hot_item(hash) {
-        move_towards(^animation_state.hover_time, 1.0f, theme.hover_speed);
-    } else {
-        move_towards(^animation_state.hover_time, 0.0f, theme.hover_speed);
-    }
-
-    box_border_width := theme.box_border_width;
-    box_size         := theme.box_size;
-
-    immediate_set_color(theme.box_color);
-    immediate_rectangle(x + 4, y + (h - box_size) / 2, box_size, box_size);
-
-    surface_color : Color;
-    if *value == set_to {
-        surface_color = theme.checked_color;
-        surface_color = color_lerp(animation_state.hover_time, surface_color, theme.checked_hover_color);
-
-    } else {
-        surface_color = theme.background_color;
-        surface_color = color_lerp(animation_state.hover_time, surface_color, theme.hover_color);
-    }
-
-    surface_color = color_lerp(animation_state.click_time, surface_color, theme.click_color);
-
-    immediate_set_color(surface_color);
-    immediate_rectangle(x + 4 + box_border_width, y + (h - box_size) / 2 + box_border_width, box_size - box_border_width * 2, box_size - box_border_width * 2);
-
-    font := font_lookup(.{theme.font_name, theme.font_size});
-    text_width  := font_get_width(font, text);
-    text_height := font_get_height(font, text);
-
-    font_set_color(theme.text_color);
-    font_draw(font, x + box_size + 4 * 2, y + font.em + (h - text_height) / 2, text);
-
-    move_towards(^animation_state.click_time, 0.0f, theme.click_decay_speed);
-
-    return result;
-}
-
-
-
-
-scrolling_region_start :: (r: Rect, max_y_scroll := 10000.0f, site := #callsite, increment := 0) {
-    hash := get_site_hash(site, increment);
-    mx, my := mouse_get_position();
-    state := ^scroll_states[hash];
-    if state == null {
-        animation_states[hash] = .{};
-        state = ^scroll_states[hash];
-    }
-
-    contains := Rect.contains(r, .{~~mx, ~~my});
-    if contains {
-        scroll_delta := mouse_get_scroll_vector();
-        state.xscroll -= scroll_delta.x * 20;
-        state.yscroll -= scroll_delta.y * 20;
-
-        state.yscroll = math.clamp(state.yscroll, 0, max_y_scroll);
-    }
-
-    immediate_flush();
-    immediate_push_scissor(r.x, r.y, r.w, r.h);
-    immediate_set_scroll(-state.xscroll, -state.yscroll);
-}
-
-scrolling_region_stop :: () {
-    immediate_flush();
-    immediate_pop_scissor();
-    immediate_set_scroll(0, 0);
-}
-
-
-
-#local {
-    hot_item    : UI_Id = 0
-    hot_item_was_set := false
-
-    hot_item_depth := 0;
-    hot_item_depth_needed := 0;
-
-    active_item : UI_Id = 0
-    active_countdown := 0
-
-    set_active_item :: (id: UI_Id) -> bool {
-        active_item = id;
-        active_countdown = 2;
-        return true;
-    }
-
-    renew_active_item :: (id: UI_Id) {
-        if active_item == id {
-            active_countdown = 2;
-        }
-    }
-
-    set_hot_item :: (id: UI_Id, force := false) -> bool {
-        if active_item != 0 do return false;
-
-        if force {
-            hot_item_was_set = true;
-            hot_item = id;
-            return true;
-        }
-
-        hot_item_depth += 1;
-        if hot_item_depth >= hot_item_depth_needed {
-            hot_item_was_set = true;
-            hot_item = id;
-            return true;
-        }
-
-        return false;
-    }
-
-    is_active_item :: (id: UI_Id) -> bool {
-        return active_item == id;
-    }
-
-    is_hot_item :: (id: UI_Id) -> bool {
-        return hot_item == id;
-    }
-
-    Text_Theme :: struct {
-        text_color := Color.{1, 1, 1};
-        font_name  := "./assets/fonts/calibri.ttf";
-        font_size  := 18;
-    }
-
-    Animation_Theme :: struct {
-        hover_speed       := 0.1f;
-        click_decay_speed := 0.08f;
-    }
-
-    Animation_State :: struct {
-        hover_time := 0.0f;
-        click_time := 0.0f;
-
-        accessed_this_frame := false;
-    }
-
-    animation_states : Map(UI_Id, Animation_State);
-
-    get_animation :: (id: UI_Id) -> ^Animation_State {
-        retval := ^animation_states[id];
-        if retval == null {
-            animation_states[id] = .{};
-            retval = ^animation_states[id];
-        }
-
-        retval.accessed_this_frame = true;
-        return retval;
-    }
-
-    has_active_animation :: () -> bool {
-        for^ animation_states.entries {
-            if it.value.hover_time != 0.0f || it.value.hover_time != 0.0f do return true;
-            if it.value.click_time != 0.0f || it.value.click_time != 0.0f do return true;
-        }
-
-        return false;
-    }
-
-
-    Scroll_State :: struct {
-        xscroll: f32;
-        yscroll: f32;
-    }
-
-    scroll_states : Map(UI_Id, Scroll_State);
-
-    get_site_hash :: (site: CallSite, increment := 0) -> UI_Id {
-        file_hash   := core.hash.to_u32(site.file);
-        line_hash   := core.hash.to_u32(site.line);
-        column_hash := core.hash.to_u32(site.column);
-
-        return ~~ (file_hash * 0x472839 + line_hash * 0x6849210 + column_hash * 0x1248382 + increment);
-    }
-
-    color_lerp :: macro (t: f32, c1, c2: Color) => Color.{
-        r = c1.r * (1 - t) + c2.r * t,
-        g = c1.g * (1 - t) + c2.g * t,
-        b = c1.b * (1 - t) + c2.b * t,
-        a = c1.a * (1 - t) + c2.a * t,
-    };
-}
diff --git a/src/ogre/vecmath.onyx b/src/ogre/vecmath.onyx
deleted file mode 100644 (file)
index 583dd2c..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-package ogre
-
-use core {hash, math, conv, string}
-
-@conv.Custom_Format.{format_vector2i}
-@conv.Custom_Parse.{parse_vector2i}
-Vector2i :: struct {
-    x, y: i32;
-    
-}
-
-@conv.Custom_Format.{format_vector2}
-@conv.Custom_Parse.{parse_vector2}
-Vector2 :: struct {
-    x, y: f32;
-
-    mag :: (v: Vector2) => math.sqrt(v.x * v.x + v.y * v.y);
-
-    square_mag :: (v: Vector2) => v.x * v.x + v.y * v.y;
-
-    norm :: (v: Vector2) -> Vector2 {
-        l := math.sqrt(v.x * v.x + v.y * v.y);
-        return .{ v.x / l, v.y / l };
-    }
-
-
-    Zero :: Vector2.{0, 0}
-}
-
-@conv.Custom_Format.{format_vector3i}
-Vector3i :: struct {
-    x, y, z: i32;
-}
-
-@conv.Custom_Format.{format_vector3}
-Vector3 :: struct {
-    x, y, z: f32;
-
-    mag :: (v: Vector3) => math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
-
-    neg :: (v: Vector3) => Vector3.{ -v.x, -v.y, -v.z };
-
-    dot :: (v1, v2: Vector3) -> f32 {
-        return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
-    }
-
-    norm :: (v: Vector3) -> Vector3 {
-        l := math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
-        return .{ v.x / l, v.y / l, v.z / l };
-    }
-
-    cross :: (v1, v2: Vector3) -> Vector3 {
-        return .{
-            v1.y * v2.z - v1.z * v2.y,
-            v1.z * v2.x - v1.x * v2.z,
-            v1.x * v2.y - v1.y * v2.x,
-        };
-    }
-
-    clamp :: (v: Vector3, min: Vector3, max: Vector3) -> Vector3 {
-        return .{
-            math.clamp(v.x, min.x, max.x),
-            math.clamp(v.y, min.y, max.y),
-            math.clamp(v.z, min.z, max.z),
-        };
-    }
-}
-
-#operator + (v1, v2: Vector2i)    => Vector2i.{ v1.x + v2.x, v1.y + v2.y };
-#operator - (v1, v2: Vector2i)    => Vector2i.{ v1.x - v2.x, v1.y - v2.y };
-#operator * (v: Vector2i, s: i32) => Vector2i.{ v.x * s,     v.y * s     };
-#operator * (v1, v2: Vector2i)    => Vector2i.{ v1.x * v2.x, v1.y * v2.y };
-#operator == (v1, v2: Vector2i)   => v1.x == v2.x && v1.y == v2.y;
-#match hash.to_u32 (v: Vector2i)  => 13 * v.x + 17 * v.y;
-
-#operator + (v1, v2: Vector2)    => Vector2.{ v1.x + v2.x, v1.y + v2.y };
-#operator - (v1, v2: Vector2)    => Vector2.{ v1.x - v2.x, v1.y - v2.y };
-#operator * (v: Vector2, s: f32) => Vector2.{ v.x * s,     v.y * s     };
-#operator * (v1, v2: Vector2)    => Vector2.{ v1.x * v2.x, v1.y * v2.y };
-#operator == (v1, v2: Vector2)   => v1.x == v2.x && v1.y == v2.y;
-
-#operator + (v1, v2: Vector3)    => Vector3.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
-#operator - (v1, v2: Vector3)    => Vector3.{ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
-#operator * (v: Vector3, s: f32) => Vector3.{ v.x * s,     v.y * s,     v.z * s };
-#operator * (v1, v2: Vector3)    => Vector3.{ v1.x * v2.x, v1.y * v2.y, v1.z * v2.z };
-#operator == (v1, v2: Vector3)   => v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
-
-#operator + (v1, v2: Vector3i)    => Vector3i.{ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
-#operator - (v1, v2: Vector3i)    => Vector3i.{ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
-#operator * (v: Vector3i, s: i32) => Vector3i.{ v.x * s,     v.y * s,     v.z * s };
-#operator * (v1, v2: Vector3i)    => Vector3i.{ v1.x * v2.x, v1.y * v2.y, v1.z * v2.z };
-#operator == (v1, v2: Vector3i)   => v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
-
-#local {
-    format_vector2i :: (output: ^conv.Format_Output, format: ^conv.Format, v: ^Vector2i) {
-        conv.format(output, "({}, {})", v.x, v.y);
-    }
-
-    format_vector2 :: (output: ^conv.Format_Output, format: ^conv.Format, v: ^Vector2) {
-        conv.format(output, "({}, {})", v.x, v.y);
-    }
-
-    format_vector3 :: (output: ^conv.Format_Output, format: ^conv.Format, v: ^Vector3) {
-        conv.format(output, "({}, {}, {})", v.x, v.y, v.z);
-    }
-
-    format_vector3i :: (output: ^conv.Format_Output, format: ^conv.Format, v: ^Vector3i) {
-        conv.format(output, "({}, {}, {})", v.x, v.y, v.z);
-    }
-
-    parse_vector2i :: (output: ^Vector2i, line_: str, string_allocator: Allocator) -> bool {
-        line := line_;
-        xs := string.read_until(^line, #char " ");
-        string.advance(^line, 1);
-        ys := string.read_until(^line, #char " ");
-
-        if xs == "" || ys == "" do return false;
-
-        output.x = ~~ conv.str_to_i64(xs);
-        output.y = ~~ conv.str_to_i64(ys);
-        return true;
-    }
-
-    parse_vector2 :: (output: ^Vector2, line_: str, string_allocator: Allocator) -> bool {
-        line := line_;
-        xs := string.read_until(^line, #char " ");
-        string.advance(^line, 1);
-        ys := string.read_until(^line, #char " ");
-
-        if xs == "" || ys == "" do return false;
-
-        output.x = ~~ conv.str_to_f64(xs);
-        output.y = ~~ conv.str_to_f64(ys);
-        return true;
-    }
-}
-
-
-
-Rect :: struct {
-    x, y, w, h: f32;
-
-    intersects :: (r1, r2: Rect) -> bool {
-        return r1.x < r2.x + r2.w
-            && r1.x + r1.w > r2.x
-            && r1.y < r2.y + r2.h
-            && r1.y + r1.h > r2.y;
-    }
-
-    contains :: (r: Rect, p: Vector2) -> bool {
-        return r.x <= p.x && r.x + r.w >= p.x
-            && r.y <= p.y && r.y + r.h >= p.y;
-    }
-
-    center :: (use r: Rect) => Vector2.{ r.x+r.w/2, r.y+r.h/2 };
-
-    top_left     :: (use r: Rect) => Vector2.{ r.x,   r.y   };
-    top_right    :: (use r: Rect) => Vector2.{ r.x+r.w, r.y   };
-    bottom_left  :: (use r: Rect) => Vector2.{ r.x,   r.y+r.h };
-    bottom_right :: (use r: Rect) => Vector2.{ r.x+r.w, r.y+r.h };
-}
diff --git a/src/ogre/window.onyx b/src/ogre/window.onyx
deleted file mode 100644 (file)
index 3c30bc0..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-package ogre
-
-use glfw3
-use opengles
-
-Window :: struct {
-    glfw_window: GLFWwindow_p;
-    width, height: i32;
-}
-
-window_create :: (width, height: i32, name: cstr) -> Window {
-    #if runtime.compiler_os == .Linux {
-        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
-        glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
-    } else {
-        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-    }
-
-    w := glfwCreateWindow(width, height, name);
-
-    return .{ w, width, height };
-}
-
-window_use :: (w: ^Window) {
-    glfwMakeContextCurrent(w.glfw_window);
-    glfwSwapInterval(1);
-
-    input_bind_glfw_events(w.glfw_window);
-
-    // Provide sensible defaults for OpenGL
-    glInit(glfwGetLoadProcAddress());
-    glEnable(GL_TEXTURE);
-    glEnable(GL_CULL_FACE);
-    glFrontFace(GL_CW);
-    glCullFace(GL_BACK);
-    glEnable(GL_BLEND);
-    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
-    glfwGetWindowSize(w.glfw_window, ^w.width, ^w.height);
-    update_view_matrix(w.width, w.height);
-
-    glfwSetWindowSizeCallback(w.glfw_window, #export_name (w: GLFWwindow_p, width, height: u32) {
-        global_window.width = width;
-        global_window.height = height;
-        update_view_matrix(width, height);
-    });
-
-    global_window = w;
-}
-
-window_should_close :: (w: ^Window) -> bool {
-    return glfwWindowShouldClose(w.glfw_window);
-}
-
-window_set_should_close :: (w: ^Window, b: bool) {
-    return glfwSetWindowShouldClose(w.glfw_window, b);
-}
-
-window_swap_buffers :: (w: ^Window) {
-    glfwSwapBuffers(w.glfw_window);
-}
-
-window_poll_events :: (_: ^Window) {
-    glfwPollEvents();
-}
-
-#inject Window {
-    should_close :: window_should_close;
-    set_should_close :: window_set_should_close;
-    swap_buffers :: window_swap_buffers;
-    poll_events :: window_poll_events;
-}
-
-//
-// These have to be macros because '#export_name' is used on the argument,
-// which requires that they are compile time known functions.
-//
-// window_size_callback :: macro (w: ^Window, resize: (w: GLFWwindow_p, width, height: u32) -> void) {
-//     glfw3.glfwSetWindowSizeCallback(w.glfw_window, #export_name resize);
-// }
-
-
-
-
-
-#package
-global_window: ^Window;
-
diff --git a/src/utils/any_utils.onyx b/src/utils/any_utils.onyx
deleted file mode 100644 (file)
index 7ded215..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// The contents of this file will probably be merged with the
-// core libraries in Onyx at some point. I just haven't flushed
-// out the details yet on what everything should exactly do and
-// be responsible for.
-//
-
-use package core
-
-ptr_to_any :: (x: ^$T) -> any {
-    return .{x, T};
-}
-
-//
-// This function looks up a member's offset and type (effectively
-// an 'any'), given the base pointer and type in the form of an
-// 'any' and the member_name, which is a '.' separate list of
-// symbols.
-//
-get_any_for_member :: (base: any, member_name: str) -> any {
-    use package runtime.info
-
-    name := member_name;
-    info := cast(^Type_Info_Struct) get_type_info(base.type);
-    assert(info.kind == .Struct, "bad type");
-
-    part_name := string.read_until(^name, #char ".");
-    string.advance(^name, 1);
-
-    for info.members {
-        if it.name == part_name {
-            member_info := get_type_info(it.type);
-            if member_info.kind == .Struct && name != "" {
-                return get_any_for_member(any.{cast(^u8) base.data + it.offset, it.type}, name);
-            } else {
-                return any.{cast(^u8) base.data + it.offset, it.type};
-            }
-        }
-    }
-
-    return .{null, void};
-}
-
-with :: macro (v: $T, body: Code) {
-    it := v;
-    #unquote body;
-}
diff --git a/src/utils/misc.onyx b/src/utils/misc.onyx
new file mode 100644 (file)
index 0000000..015dc6f
--- /dev/null
@@ -0,0 +1,13 @@
+package main
+
+use core {math}
+
+move_towards :: (v: ^$T, target: T, diff: T) {
+    if math.abs(target - *v) <= diff {
+        *v = target;
+        return;
+    }
+
+    if *v < target do *v += diff;
+    if *v > target do *v -= diff;
+}