#include "engine.h" #include "ui_lua.h" #include "gpu.h" #include "draw.h" void text_callback(GLFWwindow* window, unsigned int codepoint) { ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); if(context->ui.active_container != NULL && ui_lua_dispatch_text( &context->ui, &context->render, context->ui.active_container, context->ui.active_layer, context->ui.active_element, codepoint)) return; if(context->app_text != NULL) context->app_text(context, codepoint); } void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { (void)scancode; (void)mods; ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); if(context->ui.active_container != NULL && ui_lua_dispatch_key( &context->ui, &context->render, context->ui.active_container, context->ui.active_layer, context->ui.active_element, key, action, mods)) return; if(context->app_key != NULL) context->app_key(context, key, action, mods); } void button_callback(GLFWwindow* window, int button, int action, int mods) { double cursor[2]; uint32_t container; uint32_t layer; uint32_t element; vec2 position; ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); glfwGetCursorPos(window, &cursor[0], &cursor[1]); if(context->ui.active_container != NULL && context->ui.active_container->script_env != 0) { Container* container_ptr = context->ui.active_container; GPUDrawable* drawable_ptr = &container_ptr->layers[context->ui.active_layer].drawables_buffer[context->ui.active_element]; vec2 element_pos = { drawable_ptr->pos[0] + container_ptr->data.offset[0], drawable_ptr->pos[1] + container_ptr->data.offset[1], }; anchor_offset(&context->render, container_ptr, element_pos); vec2 element_size = { drawable_ptr->size[0], drawable_ptr->size[1], }; vec2 point = { (cursor[0] - element_pos[0])/element_size[0], (cursor[1] - element_pos[1])/element_size[1], }; if((point[0] <= 1 && point[0] >= 0 && point[1] <= 1 && point[1] >= 0) || action == GLFW_RELEASE) { ui_lua_dispatch_button( &context->ui, &context->render, container_ptr, context->ui.active_layer, context->ui.active_element, point[0], point[1], button, action, mods); return; } else { clear_active_element(&context->ui, &context->render); } } if(ui_intersect(cursor, &context->render, &context->ui, UI_EVENT_BUTTON, &container, &layer, &element, position)) { Container* container_ptr = context_container(container, &context->ui); if(ui_lua_dispatch_button( &context->ui, &context->render, container_ptr, layer, element, position[0], position[1], button, action, mods)) return; } if(context->app_button != NULL) context->app_button(context, cursor[0], cursor[1], button, action, mods); } void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { (void)xoffset; uint32_t container; uint32_t layer; uint32_t element; vec2 position; ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); if(context->ui.active_container != NULL && ui_lua_dispatch_scroll( &context->ui, &context->render, context->ui.active_container, context->ui.active_layer, context->ui.active_element, xoffset, yoffset)) return; if(ui_intersect( context->ui.cursor, &context->render, &context->ui, UI_EVENT_SCROLL, &container, &layer, &element, position)) { Container* container_ptr = context_container(container, &context->ui); ui_lua_dispatch_scroll( &context->ui, &context->render, container_ptr, layer, element, xoffset, yoffset); } if(context->app_scroll != NULL) context->app_scroll(context, xoffset, yoffset); } void cursor_callback(GLFWwindow* window, double xpos, double ypos) { ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); uint32_t container; uint32_t element; uint32_t layer; vec2 position; context->ui.cursor[0] = xpos; context->ui.cursor[1] = ypos; if(context->ui.active_container != NULL && context->ui.active_container->script_env != 0) { Container* container_ptr = context->ui.active_container; GPUDrawable* drawable_ptr = &container_ptr->layers[context->ui.active_layer].drawables_buffer[context->ui.active_element]; vec2 element_pos = { drawable_ptr->pos[0] + container_ptr->data.offset[0], drawable_ptr->pos[1] + container_ptr->data.offset[1], }; anchor_offset(&context->render, container_ptr, element_pos); vec2 element_size = { drawable_ptr->size[0], drawable_ptr->size[1], }; if(ui_lua_dispatch_cursor( &context->ui, &context->render, container_ptr, context->ui.active_layer, context->ui.active_element, (context->ui.cursor[0] - element_pos[0])/element_size[0], (context->ui.cursor[1] - element_pos[1])/element_size[1])) return; } if(ui_intersect(context->ui.cursor, &context->render, &context->ui, UI_EVENT_CURSOR, &container, &layer, &element, position)) { Container* container_ptr = context_container(container, &context->ui); ui_lua_dispatch_cursor( &context->ui, &context->render, container_ptr, layer, element, position[0], position[1]); } if(context->app_cursor != NULL) context->app_cursor(context, xpos, ypos); } int app_main(ClientContext* context) { VkResult result; // double last_frame_time = 0; while(glfwWindowShouldClose(context->window) == 0) { double frame_time = glfwGetTime(); double delta_time = (frame_time - last_frame_time); // Reset callback variables context->zoom = 0; glfwPollEvents(); if(context->app_frame != NULL) context->app_frame(context); if((context->spin[0] != 0 || context->spin[1] != 0 || context->velocity[0] != 0 || context->velocity[1] != 0 || context->velocity[2] != 0 || context->zoom != 0 || context->render.framebuffer_recreated == true)) { if(context->render.framebuffer_recreated == true) { context->render.framebuffer_recreated = false; VK_RESULT(update_hex_proj(&context->render, &context->hex)); VK_RESULT(update_ui_context_resolution(&context->ui, &context->render)); } context->rotation[0] += (float)context->spin[0]*delta_time*context->spin_speed; if(context->rotation[0] > 2*M_PI) { context->rotation[0] -= 2*M_PI; } else if(context->rotation[0] < 0) { context->rotation[0] += 2*M_PI; } context->rotation[1] += (float)context->spin[1]*delta_time*context->spin_speed; if(context->rotation[1] > (M_PI/2 - 0.1)) { context->rotation[1] = (M_PI/2 - 0.1); } else if(context->rotation[1] < 0) { context->rotation[1] = 0; } context->position[0] += - context->velocity[2]*context->move_speed*cos(context->rotation[0]) - context->velocity[0]*context->move_speed*sin(context->rotation[0]); context->position[2] += context->velocity[0]*context->move_speed*cos(context->rotation[0]) - context->velocity[2]*context->move_speed*sin(context->rotation[0]); context->position[1] += context->velocity[1]*context->move_speed; context->distance += context->zoom*delta_time*context->zoom_speed; if(context->distance < 1) { context->distance = 1; } VK_RESULT(update_hex_view( context->position, context->rotation, context->distance, &context->render, &context->hex)); } // VkResult result = draw_frame(&context->render, &context->ui, &context->hex, frame_time); if(result != VK_SUCCESS) { fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); glfwDestroyWindow(context->window); } last_frame_time = frame_time; } return 0; } int run_app( void* app_data, app_startup_function app_startup, app_frame_function app_frame, app_text_callback app_text, app_key_callback app_key, app_button_callback app_button, app_scroll_callback app_scroll, app_cursor_callback app_cursor) { ClientContext* context = malloc(sizeof(ClientContext)); if(context == NULL) { return -1; } memset(context, 0, sizeof(ClientContext)); context->window = init_window(); context->rotation[0] = 3*M_PI/2; context->rotation[1] = M_PI/4; context->distance = 25; context->spin_speed = 1.0; context->zoom_speed = 1.0; context->move_speed = 0.1; memset(&context->render, 0, sizeof(RenderContext)); memset(&context->ui, 0, sizeof(UIContext)); memset(&context->hex, 0, sizeof(HexContext)); context->app_data = app_data; context->app_frame = app_frame; context->app_text = app_text; context->app_key = app_key; context->app_button = app_button; context->app_scroll = app_scroll; context->app_cursor = app_cursor; glfwSetWindowUserPointer(context->window, context); glfwSetKeyCallback(context->window, key_callback); glfwSetMouseButtonCallback(context->window, button_callback); glfwSetScrollCallback(context->window, scroll_callback); glfwSetCursorPosCallback(context->window, cursor_callback); glfwSetCharCallback(context->window, text_callback); if(init_vulkan(context->window, &context->render) != VK_SUCCESS) return -2; // TODO: make # of fonts/textures/containers scaling, recreate GPU buffers as necessary if(create_ui_context(10, 10, 10, &context->render, &context->ui) != VK_SUCCESS) return -3; if(create_hex_context(&context->render, &context->hex) != VK_SUCCESS) return -4; if(app_startup != NULL) app_startup(context); return app_main(context); }