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