get working on linux (kinda), implement hash table
							parent
							
								
									112d0bbb8e
								
							
						
					
					
						commit
						11a53fa087
					
				| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
[
 | 
			
		||||
  {
 | 
			
		||||
    "arguments": [
 | 
			
		||||
      "/nix/store/qhpw32pz39y6i30b3vrbw5fw6zv5549f-gcc-wrapper-13.2.0/bin/cc",
 | 
			
		||||
      "-c",
 | 
			
		||||
      "-Ivendor/",
 | 
			
		||||
      "-g",
 | 
			
		||||
      "-Wall",
 | 
			
		||||
      "-Wextra",
 | 
			
		||||
      "-o",
 | 
			
		||||
      "bin/an_editor.o",
 | 
			
		||||
      "src/main.c"
 | 
			
		||||
    ],
 | 
			
		||||
    "directory": "/home/patrick/Documents/an_editor",
 | 
			
		||||
    "file": "/home/patrick/Documents/an_editor/src/main.c",
 | 
			
		||||
    "output": "/home/patrick/Documents/an_editor/bin/an_editor.o"
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										37
									
								
								flake.nix
								
								
								
								
							
							
						
						
									
										37
									
								
								flake.nix
								
								
								
								
							| 
						 | 
				
			
			@ -14,14 +14,21 @@
 | 
			
		|||
        };
 | 
			
		||||
        naga-cli = pkgs.rustPlatform.buildRustPackage rec {
 | 
			
		||||
          pname = "naga-cli";
 | 
			
		||||
          version = "0.19.0";
 | 
			
		||||
          version = "v0.19.0";
 | 
			
		||||
 | 
			
		||||
          src = pkgs.fetchCrate {
 | 
			
		||||
            inherit pname version;
 | 
			
		||||
            hash = "sha256-zR7Al5aMG8VTdjZwaZtjeDFI6WFD0N6MCrrLP/9PeZ8=";
 | 
			
		||||
          src = pkgs.fetchFromGitHub {
 | 
			
		||||
            name = "wgpu";
 | 
			
		||||
            owner = "gfx-rs";
 | 
			
		||||
            repo = "wgpu";
 | 
			
		||||
            rev = "a63bec8cd67b4abe3b9717e1926a94d1035b830a"; # trunk as of 2024-03-15
 | 
			
		||||
            hash = "sha256-AzsR24NAVYgrC/kWGXiWxyMERiLJ/Jink21P4oh8lOw=";
 | 
			
		||||
          };
 | 
			
		||||
          buildAndTestSubdir = "naga-cli";
 | 
			
		||||
 | 
			
		||||
          cargoHash = "sha256-/5srWh4CjD8S/hRFRTJE//X6TgIfbwnMKmgRMjX3084=";
 | 
			
		||||
          cargoLock = {
 | 
			
		||||
            lockFile = "${src}/Cargo.lock";
 | 
			
		||||
            allowBuiltinFetchGit = true;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      in
 | 
			
		||||
      {
 | 
			
		||||
| 
						 | 
				
			
			@ -30,13 +37,31 @@
 | 
			
		|||
            pkg-config
 | 
			
		||||
            binutils
 | 
			
		||||
            clang
 | 
			
		||||
            bear
 | 
			
		||||
            naga-cli
 | 
			
		||||
            darwin.apple_sdk.frameworks.Kernel
 | 
			
		||||
            darwin.apple_sdk.frameworks.CoreVideo
 | 
			
		||||
            darwin.apple_sdk.frameworks.Metal
 | 
			
		||||
            darwin.apple_sdk.frameworks.MetalKit
 | 
			
		||||
            darwin.apple_sdk.frameworks.Cocoa
 | 
			
		||||
          ]  else throw "unsupported system" );
 | 
			
		||||
          ] else if pkgs.system == "x86_64-linux" then [
 | 
			
		||||
            pkg-config
 | 
			
		||||
            binutils
 | 
			
		||||
            clang
 | 
			
		||||
            bear
 | 
			
		||||
            naga-cli
 | 
			
		||||
            libGL
 | 
			
		||||
            mesa
 | 
			
		||||
            gf
 | 
			
		||||
            xorg.libX11
 | 
			
		||||
            xorg.libXi
 | 
			
		||||
            xorg.xinput
 | 
			
		||||
            xorg.libXcursor
 | 
			
		||||
            xorg.libXrandr
 | 
			
		||||
            xorg.libXinerama
 | 
			
		||||
            pkgs.nixgl.nixGLIntel
 | 
			
		||||
          ] 
 | 
			
		||||
          else throw "unsupported system" );
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								justfile
								
								
								
								
							
							
						
						
									
										11
									
								
								justfile
								
								
								
								
							| 
						 | 
				
			
			@ -3,13 +3,14 @@ alias r := run
 | 
			
		|||
 | 
			
		||||
build: transpile_shaders_metal
 | 
			
		||||
    mkdir -p bin
 | 
			
		||||
    cc -Ivendor/ -g -Wall -Wextra -framework Cocoa -framework QuartzCore -framework CoreImage -framework Metal -framework MetalKit -ObjC src/*.c -o bin/an_editor
 | 
			
		||||
    # cc -Ivendor/ -g -Wall -Wextra -framework Cocoa -framework QuartzCore -framework CoreImage -framework Metal -framework MetalKit -ObjC src/*.c -o bin/an_editor
 | 
			
		||||
    cc -Ivendor/ -g -Wall -Wextra src/*.c -o bin/an_editor -lEGL -lGLESv2 -lGL -lm -lX11 -lXi -lXcursor
 | 
			
		||||
    # cc bin/*.o -o bin/an_editor -lEGL -lGLESv2 -lGL -lm -lX11 -lXi -lXcursor
 | 
			
		||||
 | 
			
		||||
run: build
 | 
			
		||||
    ./bin/an_editor
 | 
			
		||||
    nixGLIntel ./bin/an_editor
 | 
			
		||||
 | 
			
		||||
transpile_shaders_metal:
 | 
			
		||||
    mkdir -p bin/transpiled_shaders
 | 
			
		||||
    ../wgpu/target/debug/naga shaders/vertex.wgsl bin/transpiled_shaders/vertex.metal --metal-version 1.2
 | 
			
		||||
    ../wgpu/target/debug/naga shaders/fragment.wgsl bin/transpiled_shaders/fragment.metal --metal-version 1.2
 | 
			
		||||
    
 | 
			
		||||
    naga shaders/vertex.wgsl bin/transpiled_shaders/vertex.metal --metal-version 1.2
 | 
			
		||||
    naga shaders/fragment.wgsl bin/transpiled_shaders/fragment.metal --metal-version 1.2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
#version 330 core
 | 
			
		||||
struct VertexOutput {
 | 
			
		||||
    vec4 position;
 | 
			
		||||
    vec2 tex_coord;
 | 
			
		||||
};
 | 
			
		||||
uniform sampler2D _group_0_binding_0_fs;
 | 
			
		||||
 | 
			
		||||
smooth in vec2 _vs2fs_location0;
 | 
			
		||||
layout(location = 0) out vec4 _fs2p_location0;
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
    VertexOutput input_ = VertexOutput(gl_FragCoord, _vs2fs_location0);
 | 
			
		||||
    float text_color = 0.0;
 | 
			
		||||
    vec4 _e8 = texture(_group_0_binding_0_fs, vec2(vec2(input_.tex_coord.x, input_.tex_coord.y)));
 | 
			
		||||
    text_color = _e8.x;
 | 
			
		||||
    float _e11 = text_color;
 | 
			
		||||
    float _e17 = text_color;
 | 
			
		||||
    _fs2p_location0 = vec4((_e11 * vec3(1.0, 1.0, 1.0)), _e17);
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
#version 330 core
 | 
			
		||||
uniform uint naga_vs_first_instance;
 | 
			
		||||
 | 
			
		||||
struct VertexInput {
 | 
			
		||||
    vec3 position;
 | 
			
		||||
    vec2 tex_coord;
 | 
			
		||||
    vec2 atlas_position;
 | 
			
		||||
    vec2 size;
 | 
			
		||||
    vec2 target_position;
 | 
			
		||||
    float y_offset;
 | 
			
		||||
    uint glyph_id;
 | 
			
		||||
};
 | 
			
		||||
struct VertexOutput {
 | 
			
		||||
    vec4 position;
 | 
			
		||||
    vec2 tex_coord;
 | 
			
		||||
};
 | 
			
		||||
uniform vec4 screen_size;
 | 
			
		||||
 | 
			
		||||
layout(location = 0) in vec3 _p2vs_location0;
 | 
			
		||||
layout(location = 1) in vec2 _p2vs_location1;
 | 
			
		||||
layout(location = 2) in vec2 _p2vs_location2;
 | 
			
		||||
layout(location = 3) in vec2 _p2vs_location3;
 | 
			
		||||
layout(location = 4) in vec2 _p2vs_location4;
 | 
			
		||||
layout(location = 5) in float _p2vs_location5;
 | 
			
		||||
smooth out vec2 _vs2fs_location0;
 | 
			
		||||
 | 
			
		||||
vec4 to_device_position(vec2 position, vec2 size) {
 | 
			
		||||
    return vec4((((position / size) * 2.0) - vec2(1.0)), 1.0, 1.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void main() {
 | 
			
		||||
    VertexInput input_ = VertexInput(_p2vs_location0, _p2vs_location1, _p2vs_location2, _p2vs_location3, _p2vs_location4, _p2vs_location5, (uint(gl_InstanceID) + naga_vs_first_instance));
 | 
			
		||||
    VertexOutput out_ = VertexOutput(vec4(0.0), vec2(0.0));
 | 
			
		||||
    vec4 vertex_pos = vec4(0.0);
 | 
			
		||||
    vec2 atlas_position = vec2(0.0);
 | 
			
		||||
    vec4 _e28 = to_device_position((((((input_.position.xy + vec2(1.0)) / vec2(2.0)) * (input_.size / vec2(2.0))) + input_.target_position) + vec2(0.0, ((input_.y_offset / 2.0) + 32.0))), screen_size.xy);
 | 
			
		||||
    vertex_pos = _e28;
 | 
			
		||||
    atlas_position = (((((input_.position.xy + vec2(1.0)) / vec2(2.0)) * input_.size) + input_.atlas_position) / vec2(1024.0));
 | 
			
		||||
    vec4 _e47 = vertex_pos;
 | 
			
		||||
    out_.position = _e47;
 | 
			
		||||
    vec2 _e49 = atlas_position;
 | 
			
		||||
    out_.tex_coord = _e49;
 | 
			
		||||
    VertexOutput _e50 = out_;
 | 
			
		||||
    gl_Position = _e50.position;
 | 
			
		||||
    _vs2fs_location0 = _e50.tex_coord;
 | 
			
		||||
    gl_Position.yz = vec2(-gl_Position.y, gl_Position.z * 2.0 - gl_Position.w);
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,23 +15,23 @@ struct VertexOutput {
 | 
			
		|||
    @location(0) tex_coord: vec2<f32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Params {
 | 
			
		||||
    screen_size: vec2<f32>,
 | 
			
		||||
}
 | 
			
		||||
// struct Params {
 | 
			
		||||
//     screen_size: vec4<f32>,
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
fn to_device_position(position: vec2<f32>, size: vec2<f32>) -> vec4<f32> {
 | 
			
		||||
    return vec4<f32>((((position / size) * 2.) - 1.), 1., 1.);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@group(0) @binding(1)
 | 
			
		||||
var<uniform> params: Params;
 | 
			
		||||
@group(0) @binding(0)
 | 
			
		||||
var<uniform> screen_size: vec4<f32>;
 | 
			
		||||
 | 
			
		||||
@vertex
 | 
			
		||||
fn vs_main(input: VertexInput) -> VertexOutput {
 | 
			
		||||
    var out: VertexOutput;
 | 
			
		||||
 | 
			
		||||
    var vertex_pos = to_device_position(((input.position.xy + 1.) / 2.) * (input.size/2.0) + input.target_position + vec2<f32>(0., (input.y_offset/2.0)+32), params.screen_size);
 | 
			
		||||
    vertex_pos.y = -vertex_pos.y;
 | 
			
		||||
    var vertex_pos = to_device_position(((input.position.xy + 1.) / 2.) * (input.size/2.0) + input.target_position + vec2<f32>(0., (input.y_offset/2.0)+32), screen_size.xy);
 | 
			
		||||
    // vertex_pos.y = -vertex_pos.y;
 | 
			
		||||
    var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2<f32>(1024);
 | 
			
		||||
 | 
			
		||||
    out.position = vertex_pos;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,5 @@
 | 
			
		|||
-DED_UI_IMPLEMENTATION
 | 
			
		||||
-DED_HT_IMPLEMENTATION
 | 
			
		||||
-DED_STRING_IMPLEMENTATION
 | 
			
		||||
-I../vendor/
 | 
			
		||||
-ObjC
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										95
									
								
								src/ht.h
								
								
								
								
							
							
						
						
									
										95
									
								
								src/ht.h
								
								
								
								
							| 
						 | 
				
			
			@ -2,21 +2,108 @@
 | 
			
		|||
 | 
			
		||||
#ifndef ED_HT_INCLUDED
 | 
			
		||||
#define ED_HT_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "string.h"
 | 
			
		||||
 | 
			
		||||
// see <https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function>
 | 
			
		||||
#define FNV_OFFSET 14695981039346656037UL
 | 
			
		||||
#define FNV_PRIME 1099511628211UL
 | 
			
		||||
#define FNV_OFFSET 14695981039346656037ULL
 | 
			
		||||
#define FNV_PRIME 1099511628211ULL
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    
 | 
			
		||||
    string key;
 | 
			
		||||
} ed_ht_slot;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    ed_ht_slot *slots;
 | 
			
		||||
    ed_ht_slot *key_slots;
 | 
			
		||||
    void *value_slots;
 | 
			
		||||
    size_t value_size;
 | 
			
		||||
    size_t capacity;
 | 
			
		||||
} ed_ht;
 | 
			
		||||
 | 
			
		||||
typedef uint64_t ht_hash_t;
 | 
			
		||||
 | 
			
		||||
#ifdef ED_HT_IMPLEMENTATION
 | 
			
		||||
 | 
			
		||||
static ht_hash_t ht_hash(string key, uint64_t mod) {
 | 
			
		||||
    ht_hash_t hash = FNV_OFFSET;
 | 
			
		||||
 | 
			
		||||
    for (size_t i=0; i<key.len; ++i) {
 | 
			
		||||
        hash *= FNV_PRIME;
 | 
			
		||||
        hash ^= key.data[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return hash % mod;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ed_ht ht_create(size_t max_entries, size_t value_size) {
 | 
			
		||||
    ed_ht_slot *key_slots = (ed_ht_slot *)malloc(max_entries * sizeof(ed_ht_slot));
 | 
			
		||||
    void *value_slots = malloc(max_entries * value_size);
 | 
			
		||||
 | 
			
		||||
    memset(key_slots, 0, max_entries * sizeof(ed_ht_slot));
 | 
			
		||||
    memset(value_slots, 0, max_entries * value_size);
 | 
			
		||||
 | 
			
		||||
    return (ed_ht) {
 | 
			
		||||
        .key_slots = key_slots,
 | 
			
		||||
        .value_slots = value_slots,
 | 
			
		||||
        .value_size = value_size,
 | 
			
		||||
        .capacity = max_entries,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ht_set(ed_ht *ht, string key, void *value) {
 | 
			
		||||
    ht_hash_t hash = ht_hash(key, ht->capacity);
 | 
			
		||||
 | 
			
		||||
    for (size_t i=hash; i<ht->capacity; ++i) {
 | 
			
		||||
        if (ht->key_slots[i].key.data == NULL || string_eq(ht->key_slots[i].key, key)) {
 | 
			
		||||
            ht->key_slots[i].key = key;
 | 
			
		||||
 | 
			
		||||
            memcpy(ht->value_slots+i*ht->value_size, value, ht->value_size);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *ht_get_slot(ed_ht *ht, size_t slot) {
 | 
			
		||||
    void *value = ht->value_slots+slot*ht->value_size;
 | 
			
		||||
 | 
			
		||||
    if (slot >= ht->capacity || !value)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *ht_get(ed_ht *ht, string key) {
 | 
			
		||||
    ht_hash_t hash = ht_hash(key, ht->capacity);
 | 
			
		||||
 | 
			
		||||
    for (size_t i=hash; i<ht->capacity; ++i) {
 | 
			
		||||
        if (ht->key_slots[i].key.data == NULL) {
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (string_eq(ht->key_slots[i].key, key)) {
 | 
			
		||||
            return ht_get_slot(ht, i);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ht_destroy(ed_ht *ht) {
 | 
			
		||||
    // TODO: destroy the hash table
 | 
			
		||||
    free(ht->key_slots);
 | 
			
		||||
    free(ht->value_slots);
 | 
			
		||||
 | 
			
		||||
    ht->key_slots = NULL;
 | 
			
		||||
    ht->value_slots = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										109
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										109
									
								
								src/main.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,10 @@
 | 
			
		|||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
// #define ARENA_IMPLEMENTATION
 | 
			
		||||
// #include <tsoding/arena.h>
 | 
			
		||||
 | 
			
		||||
#define SOKOL_DEBUG
 | 
			
		||||
 | 
			
		||||
#define SOKOL_APP_IMPL
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +12,11 @@
 | 
			
		|||
#define SOKOL_GLUE_IMPL
 | 
			
		||||
#define SOKOL_FETCH_IMPL
 | 
			
		||||
#define SOKOL_LOG_IMPL
 | 
			
		||||
#define SOKOL_METAL
 | 
			
		||||
 | 
			
		||||
// TODO: condition compilation
 | 
			
		||||
// #define SOKOL_METAL
 | 
			
		||||
#define SOKOL_GLCORE33
 | 
			
		||||
 | 
			
		||||
#include <sokol/sokol_log.h>
 | 
			
		||||
#include <sokol/sokol_gfx.h>
 | 
			
		||||
#include <sokol/sokol_app.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -18,21 +26,22 @@
 | 
			
		|||
#define STB_TRUETYPE_IMPLEMENTATION
 | 
			
		||||
#include <stb/std_truetype.h>
 | 
			
		||||
 | 
			
		||||
#define ARENA_IMPLEMENTATION
 | 
			
		||||
#include <tsoding/arena.h>
 | 
			
		||||
 | 
			
		||||
#include "string.h"
 | 
			
		||||
 | 
			
		||||
#define ED_STRING_IMPLEMENTATION
 | 
			
		||||
#define ED_HT_IMPLEMENTATION
 | 
			
		||||
#define ED_UI_IMPLEMENTATION
 | 
			
		||||
#include "string.h"
 | 
			
		||||
#include "ht.h"
 | 
			
		||||
#include "ui.h"
 | 
			
		||||
 | 
			
		||||
static Arena default_arena = {0};
 | 
			
		||||
static Arena temporary_arena = {0};
 | 
			
		||||
static Arena *context_arena = &default_arena;
 | 
			
		||||
 | 
			
		||||
// static Arena default_arena = {0};
 | 
			
		||||
// static Arena temporary_arena = {0};
 | 
			
		||||
// static Arena *context_arena = &default_arena;
 | 
			
		||||
 | 
			
		||||
void *context_alloc(size_t size) {
 | 
			
		||||
    // assert(context_arena);
 | 
			
		||||
    return arena_alloc(context_arena, size);
 | 
			
		||||
    // return arena_alloc(context_arena, size);
 | 
			
		||||
    return malloc(size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +58,7 @@ typedef struct {
 | 
			
		|||
} GpuGlyph;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    float screen_size[2];
 | 
			
		||||
    float screen_size[4];
 | 
			
		||||
} GpuUniformParams;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -94,35 +103,35 @@ static struct {
 | 
			
		|||
    U8Array glyph_cache;
 | 
			
		||||
 | 
			
		||||
    bool should_exit;
 | 
			
		||||
 | 
			
		||||
    ui_context ui_cx;
 | 
			
		||||
} state;
 | 
			
		||||
 | 
			
		||||
void queue_text(string text, float position[2]) {
 | 
			
		||||
    float x = 0;
 | 
			
		||||
    for (size_t i=0; i < text.len; ++i) {
 | 
			
		||||
        if (text.data[i] >= 32 && text.data[i] <= 32+95) {
 | 
			
		||||
        if (text.data[i] >= 32) {
 | 
			
		||||
            GpuGlyph glyph = *((GpuGlyph *)(state.glyph_cache.data+((text.data[i] - 32) * sizeof(GpuGlyph))));
 | 
			
		||||
 | 
			
		||||
            glyph.position[0] = x+position[0];
 | 
			
		||||
            glyph.position[1] = position[1];
 | 
			
		||||
            x += glyph.size[0]/2;
 | 
			
		||||
 | 
			
		||||
            push_u8array(&state.gpu_glyphs, &glyph, sizeof(GpuGlyph));
 | 
			
		||||
            push_u8array(&state.gpu_glyphs, (uint8_t *)(&glyph), sizeof(GpuGlyph));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void vertex_shader_loaded(const sfetch_response_t *response) {
 | 
			
		||||
    if (response->fetched) {
 | 
			
		||||
        state.scratch_shader_desc.vs.source = response->data.ptr;
 | 
			
		||||
        state.scratch_shader_desc.vs.entry = "vs_main";
 | 
			
		||||
        state.scratch_shader_desc.vs = (sg_shader_stage_desc) {
 | 
			
		||||
            .source = response->data.ptr,
 | 
			
		||||
            .entry = "vs_main",
 | 
			
		||||
            .uniform_blocks[0] = {
 | 
			
		||||
                .size = sizeof(GpuUniformParams),
 | 
			
		||||
                .layout = SG_UNIFORMLAYOUT_NATIVE,
 | 
			
		||||
                .layout = SG_UNIFORMLAYOUT_STD140,
 | 
			
		||||
                .uniforms = {
 | 
			
		||||
                    [0] = { .name = "screen_size", .type = SG_UNIFORMTYPE_FLOAT2 },
 | 
			
		||||
                    [0] = { .name = "screen_size", .type = SG_UNIFORMTYPE_FLOAT4 },
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +148,7 @@ void fragment_shader_loaded(const sfetch_response_t *response) {
 | 
			
		|||
            .entry = "fs_main",
 | 
			
		||||
            .images[0].used = true,
 | 
			
		||||
            .samplers[0].used = true,
 | 
			
		||||
            .image_sampler_pairs[0] = { .used = true, .image_slot = 0, .sampler_slot = 0 },
 | 
			
		||||
            .image_sampler_pairs[0] = { .glsl_name = "_group_0_binding_0_fs", .used = true, .image_slot = 0, .sampler_slot = 0 },
 | 
			
		||||
        };
 | 
			
		||||
        state.scratch_shader_desc.fs.source = response->data.ptr;
 | 
			
		||||
        state.scratch_shader_desc.fs.entry = "fs_main";
 | 
			
		||||
| 
						 | 
				
			
			@ -151,11 +160,12 @@ void fragment_shader_loaded(const sfetch_response_t *response) {
 | 
			
		|||
 | 
			
		||||
void ed_init() {
 | 
			
		||||
    uint8_t ttf_buffer[1<<20];
 | 
			
		||||
    FILE *ttf_file = fopen("../c_editor/JetBrainsMono-Medium.ttf", "rb");
 | 
			
		||||
    // TODO: grab default font from the system
 | 
			
		||||
    FILE *ttf_file = fopen("./bin/JetBrainsMono-Medium.ttf", "rb");
 | 
			
		||||
    if (!ttf_file) {
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    fread(ttf_buffer, 1, 1<<20, ttf_file);
 | 
			
		||||
    assert(fread(ttf_buffer, 1, 1<<20, ttf_file));
 | 
			
		||||
    fclose(ttf_file);
 | 
			
		||||
 | 
			
		||||
    stbtt_fontinfo font;
 | 
			
		||||
| 
						 | 
				
			
			@ -163,10 +173,11 @@ void ed_init() {
 | 
			
		|||
 | 
			
		||||
    sg_setup(&(sg_desc) {
 | 
			
		||||
        .environment = sglue_environment(),
 | 
			
		||||
        .logger.func = slog_func,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    float vertices[] = {
 | 
			
		||||
        // positions            colors
 | 
			
		||||
        // positions            texture coords
 | 
			
		||||
        -1.0f,  1.0f, 1.0f,     0.0f, 0.0f,
 | 
			
		||||
         1.0f,  1.0f, 1.0f,     1.0f, 0.0f,
 | 
			
		||||
         1.0f, -1.0f, 1.0f,     1.0f, 1.0f,
 | 
			
		||||
| 
						 | 
				
			
			@ -188,12 +199,24 @@ void ed_init() {
 | 
			
		|||
    char fs_source[8000] = { 0 };
 | 
			
		||||
 | 
			
		||||
    sfetch_handle_t vs_handle = sfetch_send(&(sfetch_request_t) {
 | 
			
		||||
#if defined (__APPLE__)
 | 
			
		||||
        .path = "./bin/transpiled_shaders/vertex.metal",
 | 
			
		||||
#elif defined (__linux__) || defined (__unix__)
 | 
			
		||||
        .path = "./shaders/vertex.vert",
 | 
			
		||||
#else
 | 
			
		||||
#error "Unsupported platform for shaders"
 | 
			
		||||
#endif
 | 
			
		||||
        .callback = vertex_shader_loaded,
 | 
			
		||||
        .buffer = { .ptr = vs_source, .size = sizeof(vs_source) },
 | 
			
		||||
    });
 | 
			
		||||
    sfetch_handle_t fs_handle = sfetch_send(&(sfetch_request_t) {
 | 
			
		||||
#if defined (__APPLE__)
 | 
			
		||||
        .path = "./bin/transpiled_shaders/fragment.metal",
 | 
			
		||||
#elif defined (__linux__) || defined (__unix__)
 | 
			
		||||
        .path = "./shaders/fragment.frag",
 | 
			
		||||
#else
 | 
			
		||||
#error "Unsupported platform for shaders"
 | 
			
		||||
#endif
 | 
			
		||||
        .callback = fragment_shader_loaded,
 | 
			
		||||
        .buffer = { .ptr = fs_source, .size = sizeof(fs_source) },
 | 
			
		||||
    });
 | 
			
		||||
| 
						 | 
				
			
			@ -221,12 +244,12 @@ void ed_init() {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // manually add glyph for SPACE
 | 
			
		||||
    push_u8array(&state.glyph_cache, &(GpuGlyph){
 | 
			
		||||
    push_u8array(&state.glyph_cache, (uint8_t *)(&(GpuGlyph){
 | 
			
		||||
        .atlas_position = { 0 },
 | 
			
		||||
        .size = { rasterized_font_height/4, rasterized_font_height },
 | 
			
		||||
        .position = { 0 },
 | 
			
		||||
        .y_offset = -rasterized_font_height,
 | 
			
		||||
    }, 1 * sizeof(GpuGlyph));
 | 
			
		||||
    }), 1 * sizeof(GpuGlyph));
 | 
			
		||||
 | 
			
		||||
    int x = rasterized_font_height/4;
 | 
			
		||||
    int y = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -239,10 +262,10 @@ void ed_init() {
 | 
			
		|||
            y += (int)((float)(ascent - descent + line_gap)*scale);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int xxx = x;
 | 
			
		||||
        for (size_t xx=0; xx < width; ++xx) {
 | 
			
		||||
            int yyy = y;
 | 
			
		||||
            for (size_t yy=0; yy < height; ++yy) {
 | 
			
		||||
        size_t xxx = x;
 | 
			
		||||
        for (size_t xx=0; xx < (size_t)width; ++xx) {
 | 
			
		||||
            size_t yyy = y;
 | 
			
		||||
            for (size_t yy=0; yy < (size_t)height; ++yy) {
 | 
			
		||||
                font_bitmap[xxx + yyy * font_bitmap_size] = bitmap[xx + yy * width];
 | 
			
		||||
 | 
			
		||||
                yyy += 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -251,12 +274,12 @@ void ed_init() {
 | 
			
		|||
            xxx += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        push_u8array(&state.glyph_cache, &(GpuGlyph){
 | 
			
		||||
        push_u8array(&state.glyph_cache, (uint8_t *)(&(GpuGlyph){
 | 
			
		||||
            .atlas_position = { (float)(x), (float)(y) },
 | 
			
		||||
            .size = { (float)width, (float)height },
 | 
			
		||||
            .position = { (float)x, (float)y },
 | 
			
		||||
            .y_offset = (float)(yoff),
 | 
			
		||||
        }, 1 * sizeof(GpuGlyph));
 | 
			
		||||
        }), 1 * sizeof(GpuGlyph));
 | 
			
		||||
 | 
			
		||||
        x += width;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -304,6 +327,28 @@ void ed_init() {
 | 
			
		|||
    queue_text(_String("But what even is text! []!@#$%^&*()_=+"), (float[]){ 0, 0 });
 | 
			
		||||
    queue_text(_String("v0.1.0"), (float[]){ 32, 128 });
 | 
			
		||||
    queue_text(_String("an_editor - what even"), (float[]){ 32, 256 });
 | 
			
		||||
 | 
			
		||||
    state.ui_cx = init_ui_context();
 | 
			
		||||
 | 
			
		||||
    string label = _String("Number 1");
 | 
			
		||||
    ht_set(&state.ui_cx.cached_elements, label, &(ui_element_cache_data) {
 | 
			
		||||
        .label = label,
 | 
			
		||||
        .size = {
 | 
			
		||||
            .axis = UI_AXIS_HORIZONTAL,
 | 
			
		||||
            .computed_size = { 200, 256 },
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < state.ui_cx.cached_elements.capacity; ++i) {
 | 
			
		||||
        if (state.ui_cx.cached_elements.key_slots[i].key.data != NULL) {
 | 
			
		||||
            string text = state.ui_cx.cached_elements.key_slots[i].key;
 | 
			
		||||
 | 
			
		||||
            ui_element_cache_data *value = ht_get(&state.ui_cx.cached_elements, text);
 | 
			
		||||
            if (value) {
 | 
			
		||||
                queue_text(text, (float[]){ (float)value->size.computed_size[0], (float)value->size.computed_size[1] });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
void ed_frame() {
 | 
			
		||||
    if (state.gpu_glyphs.size > 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -315,8 +360,10 @@ void ed_frame() {
 | 
			
		|||
 | 
			
		||||
    GpuUniformParams gpu_uniform_params = {
 | 
			
		||||
        .screen_size = {
 | 
			
		||||
            sapp_width(),
 | 
			
		||||
            sapp_height()
 | 
			
		||||
            sapp_widthf(),
 | 
			
		||||
            sapp_heightf(),
 | 
			
		||||
            0,
 | 
			
		||||
            0
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								src/string.h
								
								
								
								
							
							
						
						
									
										19
									
								
								src/string.h
								
								
								
								
							| 
						 | 
				
			
			@ -2,12 +2,25 @@
 | 
			
		|||
#define ED_STRING_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define _String(text) ((string) { .data = text, .len = sizeof(text) })
 | 
			
		||||
#define _String(text) ((string) { .data = (uint8_t*) text, .len = sizeof(text) })
 | 
			
		||||
typedef struct {
 | 
			
		||||
    char *data;
 | 
			
		||||
    uint8_t *data;
 | 
			
		||||
    size_t len;
 | 
			
		||||
} string;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ED_STRING_IMPLEMENTATION
 | 
			
		||||
bool string_eq(string a, string b) {
 | 
			
		||||
    if (a.len != b.len) return false;
 | 
			
		||||
 | 
			
		||||
    for (size_t i=0; i<a.len; ++i) {
 | 
			
		||||
        if (a.data[i] != b.data[i]) return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								src/ui.h
								
								
								
								
							
							
						
						
									
										16
									
								
								src/ui.h
								
								
								
								
							| 
						 | 
				
			
			@ -6,7 +6,8 @@
 | 
			
		|||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "string.h"
 | 
			
		||||
 | 
			
		||||
#include "ht.h"
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    UI_AXIS_HORIZONTAL,
 | 
			
		||||
| 
						 | 
				
			
			@ -72,10 +73,19 @@ typedef struct {
 | 
			
		|||
} ui_element_frame_data;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    ed_ht *cached_elements;
 | 
			
		||||
    ed_ht cached_elements;
 | 
			
		||||
} ui_context;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ED_UI_IMPLEMENTATION
 | 
			
		||||
 | 
			
		||||
ui_context init_ui_context() {
 | 
			
		||||
    ed_ht cached_elements = ht_create(32, sizeof(ui_element_cache_data));
 | 
			
		||||
 | 
			
		||||
    return (ui_context) {
 | 
			
		||||
        .cached_elements = cached_elements,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue