#include #include #include #include #include #include #include #include "toml.h" #define MAX_VERTEX_BUFFER 512 * 1024 #define MAX_ELEMENT_BUFFER 128 * 1024 #define NK_INCLUDE_FIXED_TYPES #define NK_INCLUDE_STANDARD_IO #define NK_INCLUDE_STANDARD_VARARGS #define NK_INCLUDE_DEFAULT_ALLOCATOR #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT #define NK_INCLUDE_FONT_BAKING #define NK_INCLUDE_DEFAULT_FONT #define NK_IMPLEMENTATION #define NK_GLFW_GL3_IMPLEMENTATION #define NK_KEYSTATE_BASED_INPUT #include "nuklear.h" #include "nuklear_glfw_gl3.h" #include "constants.h" #include "logger.h" #include "main.h" #include "process_url.h" #include "style.h" #include "ui.h" #include "unifont.h" #include "utils/ffmpeg.h" extern int win_width, win_height; static char *cookie; extern void load_ui(struct ui_struct *); static void error_callback(int e, const char *d) { printf("Error %d: %s\n", e, d); } int main(void) { struct ui_struct ui; /* Set locale*/ setlocale(LC_ALL, ".UTF-8"); /* Parse config */ // NOTICE: string parsed from toml should always be freed afterwards!!! { FILE *fp; const char *config_file = "config.toml"; char errbuf[UCHAR_MAX]; fp = fopen(config_file, "r"); if (!fp) { fprintf(stderr, "[tomlc99] Cannot open %s, applying default config...\n", config_file); } else { toml_table_t *conf = toml_parse_file(fp, errbuf, sizeof(errbuf)); fclose(fp); if (!conf) { fprintf(stderr, "[tomlc99] Cannot parse %s\n", config_file); } toml_datum_t cookie_datum = toml_string_in(conf, "cookie"); if (cookie_datum.ok) { printf("[tomlc99] Found cookie string in config.toml, applying...\n"); cookie = cookie_datum.u.s; } } } /* Curl */ curl_init(cookie); /* GLFW */ struct nk_glfw glfw = {0}; static GLFWwindow *win; glfwSetErrorCallback(error_callback); if (!glfwInit()) { fprintf(stdout, "[GFLW] failed to init!\n"); exit(EXIT_FAILURE); } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif win = glfwCreateWindow(win_width, win_height, APP_NAME, NULL, NULL); if (!win) { // Window creation failed fprintf(stdout, "[GLFW] failed to create window. Does this platform " "support OpenGL 3.3+?\n"); printf("GL_VERSION_3_3: %s", glewIsSupported("GL_VERSION_3_3") ? "yes" : "no"); exit(EXIT_FAILURE); } glfwMakeContextCurrent(win); /* Glew */ glewExperimental = GL_TRUE; GLenum err; if ((err = glewInit()) != GLEW_OK) { /* Problem: glewInit failed, something is seriously wrong. */ fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); exit(EXIT_FAILURE); } /* Logger setup */ struct logger *logger = setup_logger(); // Put it in ui_struct ui.logger = logger; /* UI stat */ status_t stat = {0}; stat.is_done = true; ui.stat = &stat; setup_stat(&stat); /* create context */ ui.ctx = nk_glfw3_init(&glfw, win, NK_GLFW3_INSTALL_CALLBACKS); /* Font */ ui.logger->font_height = 24; { struct nk_font_atlas *atlas; struct nk_font_config cfg = nk_font_config(0); /* NOTICE: Some CJK fonts may have incorrect glyph indexes. https://github.com/Immediate-Mode-UI/Nuklear/issues/399 https://github.com/Immediate-Mode-UI/Nuklear/issues/542 FIX: https://github.com/Immediate-Mode-UI/Nuklear/pull/531 */ cfg.range = nk_font_chinese_glyph_ranges(); // const nk_rune ranges[] = {0x4E00, 0x9FAF, 0x0020, 0x00FF, 0x3000, // 0x30FF, 0x31F0, 0x31FF, 0xFF00, 0xFFEF, // // 0}; // cfg.range = ranges; cfg.oversample_h = 1; cfg.oversample_v = 1; nk_glfw3_font_stash_begin(&glfw, &atlas); atlas->default_font = nk_font_atlas_add_compressed_base85( atlas, unifont_compressed_data_base85, ui.logger->font_height, &cfg); nk_glfw3_font_stash_end(&glfw); } /* TextEdit */ struct nk_text_edit text_edit; nk_textedit_init_default(&text_edit); logger->text_edit = &text_edit; /* Scrollbar */ struct nk_scroll scrollbar = {0}; logger->scrollbar = &scrollbar; /* Theming */ set_style(ui.ctx, THEME_DARK); while (!glfwWindowShouldClose(win)) { /* Input */ glfwPollEvents(); nk_glfw3_new_frame(&glfw); /* Response to window resize */ glfwGetWindowSize(win, &win_width, &win_height); nk_window_set_bounds(ui.ctx, APP_NAME, nk_rect(0, 0, win_width, win_height)); /* GUI */ if (nk_begin(ui.ctx, APP_NAME, nk_rect(0, 0, win_width, win_height), NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_TITLE)) { load_ui(&ui); } nk_end(ui.ctx); /* Draw */ glfwGetWindowSize(win, &win_width, &win_height); glViewport(0, 0, win_width, win_height); glClear(GL_COLOR_BUFFER_BIT); nk_glfw3_render(&glfw, NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER); glfwSwapBuffers(win); } curl_cleanup(&stat); nk_glfw3_shutdown(&glfw); glfwTerminate(); return 0; }