334 lines
11 KiB
C
334 lines
11 KiB
C
#include "engine.h"
|
|
#include "gpu.h"
|
|
#include "draw.h"
|
|
|
|
void text_callback(GLFWwindow* window, unsigned int codepoint) {
|
|
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
|
|
if(context->ui.active_callbacks != NULL
|
|
&& context->ui.active_callbacks->text != NULL
|
|
&& context->ui.active_callbacks->text(
|
|
context->ui.active_container,
|
|
context->ui.active_callbacks->data,
|
|
&context->ui,
|
|
&context->render,
|
|
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_callbacks != NULL
|
|
&& context->ui.active_callbacks->key != NULL
|
|
&& context->ui.active_callbacks->key(
|
|
context->ui.active_container,
|
|
context->ui.active_callbacks->data,
|
|
&context->ui,
|
|
&context->render,
|
|
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_callbacks != NULL && context->ui.active_callbacks->button != NULL) {
|
|
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) {
|
|
context->ui.active_callbacks->button(
|
|
context->ui.active_container,
|
|
context->ui.active_callbacks->data,
|
|
&context->ui,
|
|
&context->render,
|
|
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);
|
|
for(uint32_t c = 0; c < container_ptr->callback_count; c++) {
|
|
if(container_ptr->callbacks[c].element == element) {
|
|
if(container_ptr->callbacks[c].button != NULL) {
|
|
if(container_ptr->callbacks[c].button(
|
|
container_ptr,
|
|
container_ptr->callbacks[c].data,
|
|
&context->ui,
|
|
&context->render,
|
|
position[0],
|
|
position[1],
|
|
button,
|
|
action,
|
|
mods)) return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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_callbacks != NULL
|
|
&& context->ui.active_callbacks->scroll != NULL
|
|
&& context->ui.active_callbacks->scroll(
|
|
context->ui.active_container,
|
|
context->ui.active_callbacks->data,
|
|
&context->ui,
|
|
&context->render,
|
|
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);
|
|
for(uint32_t c = 0; c < container_ptr->callback_count; c++) {
|
|
if(container_ptr->callbacks[c].element == element) {
|
|
if(container_ptr->callbacks[c].scroll != NULL) {
|
|
container_ptr->callbacks[c].scroll(
|
|
container_ptr,
|
|
container_ptr->callbacks[c].data,
|
|
&context->ui,
|
|
&context->render,
|
|
xoffset,
|
|
yoffset);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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_callbacks != NULL && context->ui.active_callbacks->cursor != NULL) {
|
|
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(context->ui.active_callbacks->cursor(
|
|
context->ui.active_container,
|
|
context->ui.active_callbacks->data,
|
|
&context->ui,
|
|
&context->render,
|
|
(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);
|
|
for(uint32_t c = 0; c < container_ptr->callback_count; c++) {
|
|
if(container_ptr->callbacks[c].element == element) {
|
|
if(container_ptr->callbacks[c].cursor != NULL) {
|
|
container_ptr->callbacks[c].cursor(
|
|
container_ptr,
|
|
container_ptr->callbacks[c].data,
|
|
&context->ui,
|
|
&context->render,
|
|
position[0],
|
|
position[1]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|