a_chat_client/src/main.c

220 lines
7.2 KiB
C

#include <curl/curl.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include <stb/std_truetype.h>
#define ED_GFX_IMPLEMENTATION
#define ED_STRING_IMPLEMENTATION
#define ED_HT_IMPLEMENTATION
#define ED_UI_IMPLEMENTATION
#define ED_BUFFER_IMPLEMENTATION
#define ED_FILE_IO_IMPLEMENTATION
#define CHAT_SLACK_IMPLEMENTATION
#include "ed_array.h"
#include "file_io.h"
#include "gfx.h"
#include "ht.h"
#include "slack_api.h"
#include "string.h"
#include "ui.h"
// 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 malloc(size);
}
static struct {
bool should_exit;
bool show_thing;
ui_context ui_cx;
gfx_context_t *gfx_cx;
} state;
void init(_gfx_frame_func frame_func) {
state.gfx_cx = gfx_init_context(frame_func, 640, 480);
state.ui_cx = ui_init_context();
// TODO: grab default font from the system
uint8_t ttf_buffer[1 << 20];
assert("failed to load font" &&
load_file(_String("./bin/JetBrainsMono-Medium.ttf"), 1 << 20,
ttf_buffer));
stbtt_fontinfo font;
stbtt_InitFont(&font, ttf_buffer,
stbtt_GetFontOffsetForIndex(ttf_buffer, 0));
const int font_bitmap_size = 512;
const int rasterized_font_height = _FONT_HEIGHT;
uint8_t *font_bitmap =
context_alloc(font_bitmap_size * font_bitmap_size * sizeof(uint8_t));
int ascent, descent, line_gap;
float scale = stbtt_ScaleForPixelHeight(&font, rasterized_font_height * 2);
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
for (size_t xx = 0; xx < rasterized_font_height / 2; ++xx) {
for (size_t yy = 0; yy < rasterized_font_height; ++yy) {
font_bitmap[xx + yy * font_bitmap_size] = 0;
}
}
// manually add glyph for SPACE
pushArray(GpuGlyph, &state.gfx_cx->glyph_cache,
((GpuGlyph){
.atlas_position = {0},
.size = {rasterized_font_height / 4, 1},
.position = {0},
.y_offset = -rasterized_font_height,
}));
int x = rasterized_font_height / 4;
int y = 0;
for (size_t i = 33; i < 33 + 96; ++i) {
int width, height, xoff, yoff;
uint8_t *bitmap = stbtt_GetCodepointBitmap(
&font, scale, scale, (int)i, &width, &height, &xoff, &yoff);
if (x + width >= font_bitmap_size) {
x = 0;
y += (int)((float)(ascent - descent + line_gap) * scale);
}
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;
}
xxx += 1;
}
pushArray(GpuGlyph, &state.gfx_cx->glyph_cache,
((GpuGlyph){
.atlas_position = {(float)(x), (float)(y)},
.size = {(float)width, (float)height},
.position = {(float)x, (float)y},
.y_offset = (float)(yoff),
}));
x += width;
}
gfx_push_texture_buffer(
state.gfx_cx, font_bitmap_size, font_bitmap_size, font_bitmap,
font_bitmap_size * font_bitmap_size * sizeof(uint8_t));
}
void render_ui_text(string text, float position[2]) {
gfx_queue_text(state.gfx_cx, text, position);
}
void render_ui_rect(float position[2], float size[2], float color[4]) {
gfx_queue_ui_rect(state.gfx_cx, position, size, 0, color);
}
void ed_frame(int mouse_x, int mouse_y, bool mouse_left_down,
bool mouse_right_down) {
state.ui_cx.frame_elements.data[0].size.computed_size[0] =
state.gfx_cx->frame_width;
state.ui_cx.frame_elements.data[0].size.computed_size[1] =
state.gfx_cx->frame_height;
uint8_t buffer[256] = {};
snprintf(buffer, 256, "Mouse X: %d, Mouse Y: %d, Mouse %s", mouse_x,
mouse_y, mouse_left_down ? "Down" : "Up");
ui_update_input(&state.ui_cx, (ui_context_input){
.mouse_x = mouse_x,
.mouse_y = mouse_y,
.mouse_left_down = mouse_left_down,
.mouse_right_down = mouse_right_down,
});
ui_element(&state.ui_cx, _String("channel sidebar"), UI_AXIS_VERTICAL,
ui_make_size(ui_children_sum, ui_fill), UI_FLAG_DRAW_BACKGROUND);
ui_push_parent(&state.ui_cx);
{
ui_element(&state.ui_cx, _String(buffer), UI_AXIS_HORIZONTAL,
ui_make_size(ui_fit_text, ui_fit_text),
UI_FLAG_DRAW_BACKGROUND | UI_FLAG_DRAW_TEXT);
if (ui_button(&state.ui_cx, _String("#dev-general")).clicked) {
printf("you clicked the dev-general button\n");
state.show_thing = !state.show_thing;
}
if (ui_button(&state.ui_cx, _String("#dev-help")).clicked) {
printf("you clicked the dev-help button\n");
}
if (state.show_thing) {
ui_interaction interaction = _ui_test_interaction(
&state.ui_cx,
ui_element(&state.ui_cx, _String("thread list"),
UI_AXIS_VERTICAL,
ui_make_size(ui_children_sum, ui_children_sum),
UI_FLAG_DRAW_BACKGROUND));
ui_push_parent(&state.ui_cx);
ui_element(&state.ui_cx, _String("List of Threads"),
UI_AXIS_VERTICAL, ui_make_size(ui_fit_text, ui_fit_text),
UI_FLAG_DRAW_BACKGROUND | UI_FLAG_DRAW_TEXT |
UI_FLAG_HOVERABLE);
if (interaction.hovering) {
if (ui_button(&state.ui_cx, _String("Thread 1")).clicked) {
printf("thread 1\n");
}
if (ui_button(&state.ui_cx, _String("Thread 2")).clicked) {
printf("thread 2\n");
}
if (ui_button(&state.ui_cx, _String("Thread 3")).clicked) {
printf("thread 3\n");
}
if (ui_button(&state.ui_cx, _String("Thread 4")).clicked) {
printf("thread 4\n");
}
}
ui_pop_parent(&state.ui_cx);
}
}
ui_pop_parent(&state.ui_cx);
ui_compute_layout(&state.ui_cx, 0);
ui_render(&state.ui_cx, render_ui_text, render_ui_rect);
ui_update_cache(&state.ui_cx, 0);
ui_prune(&state.ui_cx);
}
int main(int argc, char *argv[]) {
/* curl_global_init(CURL_GLOBAL_ALL);
slack_client client = slack_init_client(_String("test token"),
_String("Cookie: test_cookie=hello")); _slack_debug_print_auth_test(&client,
_String("test token"), _String("Cookie: test_cookie=hello"));
curl_global_cleanup();
return 0;
*/
init(ed_frame);
while (keep_running) {
gfx_run_events(state.gfx_cx);
}
}