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 {
 | 
					        naga-cli = pkgs.rustPlatform.buildRustPackage rec {
 | 
				
			||||||
          pname = "naga-cli";
 | 
					          pname = "naga-cli";
 | 
				
			||||||
          version = "0.19.0";
 | 
					          version = "v0.19.0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          src = pkgs.fetchCrate {
 | 
					          src = pkgs.fetchFromGitHub {
 | 
				
			||||||
            inherit pname version;
 | 
					            name = "wgpu";
 | 
				
			||||||
            hash = "sha256-zR7Al5aMG8VTdjZwaZtjeDFI6WFD0N6MCrrLP/9PeZ8=";
 | 
					            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
 | 
					      in
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
| 
						 | 
					@ -30,13 +37,31 @@
 | 
				
			||||||
            pkg-config
 | 
					            pkg-config
 | 
				
			||||||
            binutils
 | 
					            binutils
 | 
				
			||||||
            clang
 | 
					            clang
 | 
				
			||||||
 | 
					            bear
 | 
				
			||||||
            naga-cli
 | 
					            naga-cli
 | 
				
			||||||
            darwin.apple_sdk.frameworks.Kernel
 | 
					            darwin.apple_sdk.frameworks.Kernel
 | 
				
			||||||
            darwin.apple_sdk.frameworks.CoreVideo
 | 
					            darwin.apple_sdk.frameworks.CoreVideo
 | 
				
			||||||
            darwin.apple_sdk.frameworks.Metal
 | 
					            darwin.apple_sdk.frameworks.Metal
 | 
				
			||||||
            darwin.apple_sdk.frameworks.MetalKit
 | 
					            darwin.apple_sdk.frameworks.MetalKit
 | 
				
			||||||
            darwin.apple_sdk.frameworks.Cocoa
 | 
					            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
 | 
					build: transpile_shaders_metal
 | 
				
			||||||
    mkdir -p bin
 | 
					    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
 | 
					run: build
 | 
				
			||||||
    ./bin/an_editor
 | 
					    nixGLIntel ./bin/an_editor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
transpile_shaders_metal:
 | 
					transpile_shaders_metal:
 | 
				
			||||||
    mkdir -p bin/transpiled_shaders
 | 
					    mkdir -p bin/transpiled_shaders
 | 
				
			||||||
    ../wgpu/target/debug/naga shaders/vertex.wgsl bin/transpiled_shaders/vertex.metal --metal-version 1.2
 | 
					    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/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>,
 | 
					    @location(0) tex_coord: vec2<f32>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Params {
 | 
					// struct Params {
 | 
				
			||||||
    screen_size: vec2<f32>,
 | 
					//     screen_size: vec4<f32>,
 | 
				
			||||||
}
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn to_device_position(position: vec2<f32>, size: vec2<f32>) -> vec4<f32> {
 | 
					fn to_device_position(position: vec2<f32>, size: vec2<f32>) -> vec4<f32> {
 | 
				
			||||||
    return vec4<f32>((((position / size) * 2.) - 1.), 1., 1.);
 | 
					    return vec4<f32>((((position / size) * 2.) - 1.), 1., 1.);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@group(0) @binding(1)
 | 
					@group(0) @binding(0)
 | 
				
			||||||
var<uniform> params: Params;
 | 
					var<uniform> screen_size: vec4<f32>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@vertex
 | 
					@vertex
 | 
				
			||||||
fn vs_main(input: VertexInput) -> VertexOutput {
 | 
					fn vs_main(input: VertexInput) -> VertexOutput {
 | 
				
			||||||
    var out: 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);
 | 
					    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;
 | 
					    // vertex_pos.y = -vertex_pos.y;
 | 
				
			||||||
    var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2<f32>(1024);
 | 
					    var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2<f32>(1024);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out.position = vertex_pos;
 | 
					    out.position = vertex_pos;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,5 @@
 | 
				
			||||||
 | 
					-DED_UI_IMPLEMENTATION
 | 
				
			||||||
 | 
					-DED_HT_IMPLEMENTATION
 | 
				
			||||||
 | 
					-DED_STRING_IMPLEMENTATION
 | 
				
			||||||
-I../vendor/
 | 
					-I../vendor/
 | 
				
			||||||
-ObjC
 | 
					-ObjC
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										95
									
								
								src/ht.h
								
								
								
								
							
							
						
						
									
										95
									
								
								src/ht.h
								
								
								
								
							| 
						 | 
					@ -2,21 +2,108 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef ED_HT_INCLUDED
 | 
					#ifndef ED_HT_INCLUDED
 | 
				
			||||||
#define ED_HT_INCLUDED
 | 
					#define ED_HT_INCLUDED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "string.h"
 | 
					#include "string.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// see <https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function>
 | 
					// see <https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function>
 | 
				
			||||||
#define FNV_OFFSET 14695981039346656037UL
 | 
					#define FNV_OFFSET 14695981039346656037ULL
 | 
				
			||||||
#define FNV_PRIME 1099511628211UL
 | 
					#define FNV_PRIME 1099511628211ULL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    
 | 
					    string key;
 | 
				
			||||||
} ed_ht_slot;
 | 
					} ed_ht_slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    ed_ht_slot *slots;
 | 
					    ed_ht_slot *key_slots;
 | 
				
			||||||
 | 
					    void *value_slots;
 | 
				
			||||||
 | 
					    size_t value_size;
 | 
				
			||||||
    size_t capacity;
 | 
					    size_t capacity;
 | 
				
			||||||
} ed_ht;
 | 
					} 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
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										109
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										109
									
								
								src/main.c
								
								
								
								
							| 
						 | 
					@ -1,6 +1,10 @@
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// #define ARENA_IMPLEMENTATION
 | 
				
			||||||
 | 
					// #include <tsoding/arena.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SOKOL_DEBUG
 | 
					#define SOKOL_DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SOKOL_APP_IMPL
 | 
					#define SOKOL_APP_IMPL
 | 
				
			||||||
| 
						 | 
					@ -8,7 +12,11 @@
 | 
				
			||||||
#define SOKOL_GLUE_IMPL
 | 
					#define SOKOL_GLUE_IMPL
 | 
				
			||||||
#define SOKOL_FETCH_IMPL
 | 
					#define SOKOL_FETCH_IMPL
 | 
				
			||||||
#define SOKOL_LOG_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_log.h>
 | 
				
			||||||
#include <sokol/sokol_gfx.h>
 | 
					#include <sokol/sokol_gfx.h>
 | 
				
			||||||
#include <sokol/sokol_app.h>
 | 
					#include <sokol/sokol_app.h>
 | 
				
			||||||
| 
						 | 
					@ -18,21 +26,22 @@
 | 
				
			||||||
#define STB_TRUETYPE_IMPLEMENTATION
 | 
					#define STB_TRUETYPE_IMPLEMENTATION
 | 
				
			||||||
#include <stb/std_truetype.h>
 | 
					#include <stb/std_truetype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ARENA_IMPLEMENTATION
 | 
					#define ED_STRING_IMPLEMENTATION
 | 
				
			||||||
#include <tsoding/arena.h>
 | 
					#define ED_HT_IMPLEMENTATION
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "string.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ED_UI_IMPLEMENTATION
 | 
					#define ED_UI_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include "string.h"
 | 
				
			||||||
 | 
					#include "ht.h"
 | 
				
			||||||
#include "ui.h"
 | 
					#include "ui.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Arena default_arena = {0};
 | 
					
 | 
				
			||||||
static Arena temporary_arena = {0};
 | 
					// static Arena default_arena = {0};
 | 
				
			||||||
static Arena *context_arena = &default_arena;
 | 
					// static Arena temporary_arena = {0};
 | 
				
			||||||
 | 
					// static Arena *context_arena = &default_arena;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *context_alloc(size_t size) {
 | 
					void *context_alloc(size_t size) {
 | 
				
			||||||
    // assert(context_arena);
 | 
					    // assert(context_arena);
 | 
				
			||||||
    return arena_alloc(context_arena, size);
 | 
					    // return arena_alloc(context_arena, size);
 | 
				
			||||||
 | 
					    return malloc(size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
| 
						 | 
					@ -49,7 +58,7 @@ typedef struct {
 | 
				
			||||||
} GpuGlyph;
 | 
					} GpuGlyph;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    float screen_size[2];
 | 
					    float screen_size[4];
 | 
				
			||||||
} GpuUniformParams;
 | 
					} GpuUniformParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
| 
						 | 
					@ -94,35 +103,35 @@ static struct {
 | 
				
			||||||
    U8Array glyph_cache;
 | 
					    U8Array glyph_cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool should_exit;
 | 
					    bool should_exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ui_context ui_cx;
 | 
				
			||||||
} state;
 | 
					} state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void queue_text(string text, float position[2]) {
 | 
					void queue_text(string text, float position[2]) {
 | 
				
			||||||
    float x = 0;
 | 
					    float x = 0;
 | 
				
			||||||
    for (size_t i=0; i < text.len; ++i) {
 | 
					    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))));
 | 
					            GpuGlyph glyph = *((GpuGlyph *)(state.glyph_cache.data+((text.data[i] - 32) * sizeof(GpuGlyph))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            glyph.position[0] = x+position[0];
 | 
					            glyph.position[0] = x+position[0];
 | 
				
			||||||
            glyph.position[1] = position[1];
 | 
					            glyph.position[1] = position[1];
 | 
				
			||||||
            x += glyph.size[0]/2;
 | 
					            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) {
 | 
					void vertex_shader_loaded(const sfetch_response_t *response) {
 | 
				
			||||||
    if (response->fetched) {
 | 
					    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) {
 | 
					        state.scratch_shader_desc.vs = (sg_shader_stage_desc) {
 | 
				
			||||||
            .source = response->data.ptr,
 | 
					            .source = response->data.ptr,
 | 
				
			||||||
            .entry = "vs_main",
 | 
					            .entry = "vs_main",
 | 
				
			||||||
            .uniform_blocks[0] = {
 | 
					            .uniform_blocks[0] = {
 | 
				
			||||||
                .size = sizeof(GpuUniformParams),
 | 
					                .size = sizeof(GpuUniformParams),
 | 
				
			||||||
                .layout = SG_UNIFORMLAYOUT_NATIVE,
 | 
					                .layout = SG_UNIFORMLAYOUT_STD140,
 | 
				
			||||||
                .uniforms = {
 | 
					                .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",
 | 
					            .entry = "fs_main",
 | 
				
			||||||
            .images[0].used = true,
 | 
					            .images[0].used = true,
 | 
				
			||||||
            .samplers[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.source = response->data.ptr;
 | 
				
			||||||
        state.scratch_shader_desc.fs.entry = "fs_main";
 | 
					        state.scratch_shader_desc.fs.entry = "fs_main";
 | 
				
			||||||
| 
						 | 
					@ -151,11 +160,12 @@ void fragment_shader_loaded(const sfetch_response_t *response) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ed_init() {
 | 
					void ed_init() {
 | 
				
			||||||
    uint8_t ttf_buffer[1<<20];
 | 
					    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) {
 | 
					    if (!ttf_file) {
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fread(ttf_buffer, 1, 1<<20, ttf_file);
 | 
					    assert(fread(ttf_buffer, 1, 1<<20, ttf_file));
 | 
				
			||||||
    fclose(ttf_file);
 | 
					    fclose(ttf_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    stbtt_fontinfo font;
 | 
					    stbtt_fontinfo font;
 | 
				
			||||||
| 
						 | 
					@ -163,10 +173,11 @@ void ed_init() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sg_setup(&(sg_desc) {
 | 
					    sg_setup(&(sg_desc) {
 | 
				
			||||||
        .environment = sglue_environment(),
 | 
					        .environment = sglue_environment(),
 | 
				
			||||||
 | 
					        .logger.func = slog_func,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    float vertices[] = {
 | 
					    float vertices[] = {
 | 
				
			||||||
        // positions            colors
 | 
					        // positions            texture coords
 | 
				
			||||||
        -1.0f,  1.0f, 1.0f,     0.0f, 0.0f,
 | 
					        -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, 0.0f,
 | 
				
			||||||
         1.0f, -1.0f, 1.0f,     1.0f, 1.0f,
 | 
					         1.0f, -1.0f, 1.0f,     1.0f, 1.0f,
 | 
				
			||||||
| 
						 | 
					@ -188,12 +199,24 @@ void ed_init() {
 | 
				
			||||||
    char fs_source[8000] = { 0 };
 | 
					    char fs_source[8000] = { 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sfetch_handle_t vs_handle = sfetch_send(&(sfetch_request_t) {
 | 
					    sfetch_handle_t vs_handle = sfetch_send(&(sfetch_request_t) {
 | 
				
			||||||
 | 
					#if defined (__APPLE__)
 | 
				
			||||||
        .path = "./bin/transpiled_shaders/vertex.metal",
 | 
					        .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,
 | 
					        .callback = vertex_shader_loaded,
 | 
				
			||||||
        .buffer = { .ptr = vs_source, .size = sizeof(vs_source) },
 | 
					        .buffer = { .ptr = vs_source, .size = sizeof(vs_source) },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    sfetch_handle_t fs_handle = sfetch_send(&(sfetch_request_t) {
 | 
					    sfetch_handle_t fs_handle = sfetch_send(&(sfetch_request_t) {
 | 
				
			||||||
 | 
					#if defined (__APPLE__)
 | 
				
			||||||
        .path = "./bin/transpiled_shaders/fragment.metal",
 | 
					        .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,
 | 
					        .callback = fragment_shader_loaded,
 | 
				
			||||||
        .buffer = { .ptr = fs_source, .size = sizeof(fs_source) },
 | 
					        .buffer = { .ptr = fs_source, .size = sizeof(fs_source) },
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
| 
						 | 
					@ -221,12 +244,12 @@ void ed_init() {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // manually add glyph for SPACE
 | 
					    // manually add glyph for SPACE
 | 
				
			||||||
    push_u8array(&state.glyph_cache, &(GpuGlyph){
 | 
					    push_u8array(&state.glyph_cache, (uint8_t *)(&(GpuGlyph){
 | 
				
			||||||
        .atlas_position = { 0 },
 | 
					        .atlas_position = { 0 },
 | 
				
			||||||
        .size = { rasterized_font_height/4, rasterized_font_height },
 | 
					        .size = { rasterized_font_height/4, rasterized_font_height },
 | 
				
			||||||
        .position = { 0 },
 | 
					        .position = { 0 },
 | 
				
			||||||
        .y_offset = -rasterized_font_height,
 | 
					        .y_offset = -rasterized_font_height,
 | 
				
			||||||
    }, 1 * sizeof(GpuGlyph));
 | 
					    }), 1 * sizeof(GpuGlyph));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int x = rasterized_font_height/4;
 | 
					    int x = rasterized_font_height/4;
 | 
				
			||||||
    int y = 0;
 | 
					    int y = 0;
 | 
				
			||||||
| 
						 | 
					@ -239,10 +262,10 @@ void ed_init() {
 | 
				
			||||||
            y += (int)((float)(ascent - descent + line_gap)*scale);
 | 
					            y += (int)((float)(ascent - descent + line_gap)*scale);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int xxx = x;
 | 
					        size_t xxx = x;
 | 
				
			||||||
        for (size_t xx=0; xx < width; ++xx) {
 | 
					        for (size_t xx=0; xx < (size_t)width; ++xx) {
 | 
				
			||||||
            int yyy = y;
 | 
					            size_t yyy = y;
 | 
				
			||||||
            for (size_t yy=0; yy < height; ++yy) {
 | 
					            for (size_t yy=0; yy < (size_t)height; ++yy) {
 | 
				
			||||||
                font_bitmap[xxx + yyy * font_bitmap_size] = bitmap[xx + yy * width];
 | 
					                font_bitmap[xxx + yyy * font_bitmap_size] = bitmap[xx + yy * width];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                yyy += 1;
 | 
					                yyy += 1;
 | 
				
			||||||
| 
						 | 
					@ -251,12 +274,12 @@ void ed_init() {
 | 
				
			||||||
            xxx += 1;
 | 
					            xxx += 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        push_u8array(&state.glyph_cache, &(GpuGlyph){
 | 
					        push_u8array(&state.glyph_cache, (uint8_t *)(&(GpuGlyph){
 | 
				
			||||||
            .atlas_position = { (float)(x), (float)(y) },
 | 
					            .atlas_position = { (float)(x), (float)(y) },
 | 
				
			||||||
            .size = { (float)width, (float)height },
 | 
					            .size = { (float)width, (float)height },
 | 
				
			||||||
            .position = { (float)x, (float)y },
 | 
					            .position = { (float)x, (float)y },
 | 
				
			||||||
            .y_offset = (float)(yoff),
 | 
					            .y_offset = (float)(yoff),
 | 
				
			||||||
        }, 1 * sizeof(GpuGlyph));
 | 
					        }), 1 * sizeof(GpuGlyph));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        x += width;
 | 
					        x += width;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -304,6 +327,28 @@ void ed_init() {
 | 
				
			||||||
    queue_text(_String("But what even is text! []!@#$%^&*()_=+"), (float[]){ 0, 0 });
 | 
					    queue_text(_String("But what even is text! []!@#$%^&*()_=+"), (float[]){ 0, 0 });
 | 
				
			||||||
    queue_text(_String("v0.1.0"), (float[]){ 32, 128 });
 | 
					    queue_text(_String("v0.1.0"), (float[]){ 32, 128 });
 | 
				
			||||||
    queue_text(_String("an_editor - what even"), (float[]){ 32, 256 });
 | 
					    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() {
 | 
					void ed_frame() {
 | 
				
			||||||
    if (state.gpu_glyphs.size > 0) {
 | 
					    if (state.gpu_glyphs.size > 0) {
 | 
				
			||||||
| 
						 | 
					@ -315,8 +360,10 @@ void ed_frame() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GpuUniformParams gpu_uniform_params = {
 | 
					    GpuUniformParams gpu_uniform_params = {
 | 
				
			||||||
        .screen_size = {
 | 
					        .screen_size = {
 | 
				
			||||||
            sapp_width(),
 | 
					            sapp_widthf(),
 | 
				
			||||||
            sapp_height()
 | 
					            sapp_heightf(),
 | 
				
			||||||
 | 
					            0,
 | 
				
			||||||
 | 
					            0
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/string.h
								
								
								
								
							
							
						
						
									
										19
									
								
								src/string.h
								
								
								
								
							| 
						 | 
					@ -2,12 +2,25 @@
 | 
				
			||||||
#define ED_STRING_INCLUDED
 | 
					#define ED_STRING_INCLUDED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stddef.h>
 | 
					#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 {
 | 
					typedef struct {
 | 
				
			||||||
    char *data;
 | 
					    uint8_t *data;
 | 
				
			||||||
    size_t len;
 | 
					    size_t len;
 | 
				
			||||||
} string;
 | 
					} 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 <stddef.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include "string.h"
 | 
					
 | 
				
			||||||
 | 
					#include "ht.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    UI_AXIS_HORIZONTAL,
 | 
					    UI_AXIS_HORIZONTAL,
 | 
				
			||||||
| 
						 | 
					@ -72,10 +73,19 @@ typedef struct {
 | 
				
			||||||
} ui_element_frame_data;
 | 
					} ui_element_frame_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    ed_ht *cached_elements;
 | 
					    ed_ht cached_elements;
 | 
				
			||||||
} ui_context;
 | 
					} ui_context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef ED_UI_IMPLEMENTATION
 | 
					#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
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue