diff --git a/client/src/main.c b/client/src/main.c index b7bacf0..60709ce 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -34,8 +34,6 @@ typedef struct ClientContextStruct { UIContext* ui; HexContext* hex; - double cursor[2]; - vec3 position; vec3 velocity; @@ -97,6 +95,55 @@ uint32_t add_hex_region(ClientContext* context) { return i; } +void hue_bar_cursor_callback(void* ptr, float x, float y) { + (void)x; + + ClientContext* context = (ClientContext*)ptr; + + if(context->ui->active_element == 0x02 && context->ui->active_container == 0x03) { + if(y < 0) y = 0; + if(y > 1) y = 1; + + Container* container = context_container(0x03, context->ui); + container->layers[0].drawables_buffer[1].color[0][0] = y; + container->layers[0].drawables_buffer[1].color[1][0] = y; + container->layers[0].drawables_buffer[1].color[2][0] = y; + container->layers[0].drawables_buffer[1].color[3][0] = y; + add_transfers( + &container->layers[0].drawables_buffer[1].color[0], + container->layers[0].drawables, + 1*sizeof(GPUDrawable) + offsetof(GPUDrawable, color), + 4*sizeof(vec4), + context->render); + } +} + +void hue_bar_button_callback(void* ptr, float x, float y, int button, int action, int mods) { + (void)mods; + (void)x; + + ClientContext* context = (ClientContext*)ptr; + if(action == GLFW_PRESS && button == GLFW_MOUSE_BUTTON_LEFT) { + set_active_element(0x03, 0x02, context->ui); + if(y < 0) y = 0; + if(y > 1) y = 1; + + Container* container = context_container(0x03, context->ui); + container->layers[0].drawables_buffer[1].color[0][0] = y; + container->layers[0].drawables_buffer[1].color[1][0] = y; + container->layers[0].drawables_buffer[1].color[2][0] = y; + container->layers[0].drawables_buffer[1].color[3][0] = y; + add_transfers( + &container->layers[0].drawables_buffer[1].color[0], + container->layers[0].drawables, + 1*sizeof(GPUDrawable) + offsetof(GPUDrawable, color), + 4*sizeof(vec4), + context->render); + } else if(action == GLFW_RELEASE && button == GLFW_MOUSE_BUTTON_LEFT) { + clear_active_element(context->ui); + } +} + VkResult color_ui(ClientContext* context) { GPUString strings[] = { { @@ -221,6 +268,14 @@ VkResult color_ui(ClientContext* context) { .num_drawables = sizeof(drawables)/sizeof(GPUDrawable), }; + UICallbacks callbacks[] = { + { + .element = 0x02, + .button = hue_bar_button_callback, + .cursor = hue_bar_cursor_callback, + }, + }; + ContainerInput container = { .layers = &layer, .layer_count = 1, @@ -228,6 +283,8 @@ VkResult color_ui(ClientContext* context) { .id = 0x03, .offset = {0, 0}, .size = {190, 150}, + .callbacks = callbacks, + .callback_count = sizeof(callbacks)/sizeof(UICallbacks), }; return create_container(&container, context->render, context->ui); @@ -687,7 +744,7 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod (void)mods; ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); - if(context->ui->active_captures & UI_EVENT_KEY) { + if(context->ui->active_callbacks != NULL && context->ui->active_callbacks->key != NULL) { // Pass key to active element } else { switch(key) { @@ -923,7 +980,6 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod } void button_callback(GLFWwindow* window, int button, int action, int mods) { - (void)mods; double cursor[2]; uint32_t container; uint32_t element; @@ -933,10 +989,35 @@ void button_callback(GLFWwindow* window, int button, int action, int mods) { glfwGetCursorPos(window, &cursor[0], &cursor[1]); - if(context->ui->active_captures & UI_EVENT_BUTTON) { - // Pass button to active element + if(context->ui->active_callbacks != NULL && context->ui->active_callbacks->button != NULL) { + Container* container_ptr = context_container(context->ui->active_container, context->ui); + GPUDrawable* drawable_ptr = container_drawable(context->ui->active_element, container_ptr); + 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], + }; + context->ui->active_callbacks->button( + context, + (cursor[0] - element_pos[0])/element_size[0], + (cursor[1] - element_pos[1])/element_size[1], + button, + action, + mods); } else if(ui_intersect(cursor, context->render, context->ui, &container, &element, position)) { - // Pass button to active UI element + 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) { + container_ptr->callbacks[c].button(context, position[0], position[1], button, action, mods); + } + break; + } + } } else { update_hex_click(cursor, context->hex, context->render); if(button == GLFW_MOUSE_BUTTON_MIDDLE) { @@ -958,9 +1039,9 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { vec2 position; ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); - if(context->ui->active_captures & UI_EVENT_SCROLL) { + if(context->ui->active_callbacks != NULL && context->ui->active_callbacks->scroll != NULL) { // Pass scroll to active element - } else if(ui_intersect(context->cursor, context->render, context->ui, &container, &element, position)) { + } else if(ui_intersect(context->ui->cursor, context->render, context->ui, &container, &element, position)) { // Pass scroll to hovered element } else { context->zoom = -yoffset; @@ -973,23 +1054,45 @@ void cursor_callback(GLFWwindow* window, double xpos, double ypos) { uint32_t element; vec2 position; vec2 last_cursor = { - context->cursor[0], - context->cursor[1], + context->ui->cursor[0], + context->ui->cursor[1], }; - context->cursor[0] = xpos; - context->cursor[1] = ypos; + context->ui->cursor[0] = xpos; + context->ui->cursor[1] = ypos; if(context->camera_mode == true) { context->cur_spin[0] = (xpos - last_cursor[0])/context->render->swapchain_extent.width*-100; context->cur_spin[1] = (ypos - last_cursor[1])/context->render->swapchain_extent.height*100; } else { - if(context->ui->active_captures & UI_EVENT_CURSOR) { - // Pass cursor to active element - } else if(ui_intersect(context->cursor, context->render, context->ui, &container, &element, position)) { - // Pass cursor to hovered element + if(context->ui->active_callbacks != NULL && context->ui->active_callbacks->cursor != NULL) { + Container* container_ptr = context_container(context->ui->active_container, context->ui); + GPUDrawable* drawable_ptr = container_drawable(context->ui->active_element, container_ptr); + 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], + }; + context->ui->active_callbacks->cursor( + context, + (context->ui->cursor[0] - element_pos[0])/element_size[0], + (context->ui->cursor[1] - element_pos[1])/element_size[1]); + } else if(ui_intersect(context->ui->cursor, context->render, context->ui, &container, &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) { + container_ptr->callbacks[c].cursor(context, position[0], position[1]); + } + break; + } + } } else { - update_hex_hover(context->cursor, context->hex, context->render); + update_hex_hover(context->ui->cursor, context->hex, context->render); } } } diff --git a/client/src/ui.c b/client/src/ui.c index 4639d35..e8cd953 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -263,7 +263,12 @@ VkResult create_container( } context->containers[index].layer_count = container->layer_count; - + context->containers[index].callbacks = malloc(sizeof(UICallbacks)*container->callback_count); + context->containers[index].callback_count = container->callback_count; + memcpy( + context->containers[index].callbacks, + container->callbacks, + sizeof(UICallbacks)*container->callback_count); return VK_SUCCESS; } @@ -1148,6 +1153,35 @@ VkResult map_string( return VK_SUCCESS; } +Container* context_container(uint32_t container_id, UIContext* ui) { + uint32_t c; + Container* ret = NULL; + for(c = 0; c < ui->max_containers; c++) { + if(ui->containers[c].id == container_id) { + ret = &ui->containers[c]; + break; + } + } + + return ret; +} + +GPUDrawable* container_drawable(uint32_t element_id, Container* container) { + if(container == NULL || element_id == 0) { + return NULL; + } + + for(uint32_t l = 0; l < container->layer_count; l++) { + for(uint32_t d = 0; d < container->layers[l].data.num_drawables; d++) { + if(container->layers[l].drawables_buffer[d].id == element_id) { + return &container->layers[l].drawables_buffer[d]; + } + } + } + + return NULL; +} + VkResult update_ui_string( char* string, uint32_t container_id, @@ -1157,18 +1191,12 @@ VkResult update_ui_string( RenderContext* gpu) { VkResult result; - uint32_t c; - for(c = 0; c < ui->max_containers; c++) { - if(ui->containers[c].id == container_id) { - break; - } - } - if(c == ui->max_containers) { + Container* container = context_container(container_id, ui); + if(container == NULL) { return VK_ERROR_UNKNOWN; } - Container* container = &ui->containers[c]; Layer* layer = &container->layers[layer_index]; layer->strings_buffer[string_index].length = strlen(string); if(strlen(string) > 0) { @@ -1223,30 +1251,13 @@ bool ui_intersect( uint32_t* container, uint32_t* element, vec2 position) { - vec2 screen = { - gpu->swapchain_extent.width/gpu->window_scale[0], - gpu->swapchain_extent.height/gpu->window_scale[1], - }; for(uint32_t c = 0; c < ui->max_containers; c++) { if(ui->containers[c].id == 0x00000000) { continue; } vec2 container_offset = {ui->containers[c].data.offset[0], ui->containers[c].data.offset[1]}; - switch(ui->containers[c].data.anchor) { - case ANCHOR_TOP_LEFT: - break; - case ANCHOR_TOP_RIGHT: - container_offset[0] += screen[0] - ui->containers[c].data.size[0]; - break; - case ANCHOR_BOTTOM_LEFT: - container_offset[1] += screen[1] - ui->containers[c].data.size[1]; - break; - case ANCHOR_BOTTOM_RIGHT: - container_offset[0] += screen[0] - ui->containers[c].data.size[0]; - container_offset[1] += screen[1] - ui->containers[c].data.size[1]; - break; - } + anchor_offset(gpu, &ui->containers[c], container_offset); for(uint32_t l = 0; l < ui->containers[c].layer_count; l++) { for(uint32_t d = 0; d < ui->containers[c].layers[l].data.num_drawables; d++) { @@ -1270,3 +1281,48 @@ bool ui_intersect( return false; } +void clear_active_element(UIContext* ui) { + ui->active_callbacks = NULL; + ui->active_element = 0; + ui->active_container = 0; +} + +void set_active_element(uint32_t container, uint32_t element, UIContext* ui) { + ui->active_container = container; + ui->active_element = element; + ui->active_callbacks = NULL; + Container* container_ptr = context_container(container, ui); + if(container_ptr == NULL) { + fprintf(stderr, "set_active_element passed invalid container id"); + return; + } + + for(uint32_t c = 0; c < container_ptr->callback_count; container_ptr++) { + if(container_ptr->callbacks[c].element == element) { + ui->active_callbacks = &container_ptr->callbacks[c]; + break; + } + } +} + +void anchor_offset(RenderContext* gpu, Container* container, vec2 offset) { + vec2 screen = { + gpu->swapchain_extent.width/gpu->window_scale[0], + gpu->swapchain_extent.height/gpu->window_scale[1], + }; + + switch(container->data.anchor) { + case ANCHOR_TOP_LEFT: + break; + case ANCHOR_TOP_RIGHT: + offset[0] += screen[0] - container->data.size[0]; + break; + case ANCHOR_BOTTOM_LEFT: + offset[1] += screen[1] - container->data.size[1]; + break; + case ANCHOR_BOTTOM_RIGHT: + offset[0] += screen[0] - container->data.size[0]; + offset[1] += screen[1] - container->data.size[1]; + break; + } +}