diff --git a/client/include/ui.h b/client/include/ui.h index b80ed15..e733b49 100644 --- a/client/include/ui.h +++ b/client/include/ui.h @@ -15,6 +15,10 @@ #define ANCHOR_BOTTOM_RIGHT 3 #define ANCHOR_CENTER 4 +#define DRAWABLE_TYPE_RECT 0 +#define DRAWABLE_TYPE_GLYPH 1 +#define DRAWABLE_TYPE_IMAGE 2 + typedef struct UIPushConstantStruct { VkDeviceAddress layer; float time; @@ -244,4 +248,16 @@ VkResult map_string( uint32_t font, UIContext* context); +VkResult update_ui_context_resolution( + UIContext* ui, + RenderContext* gpu); + +VkResult update_ui_string( + char* string, + uint32_t container_index, + uint32_t layer_index, + uint32_t string_index, + UIContext* ui, + RenderContext* gpu); + #endif diff --git a/client/shader/string.comp b/client/shader/string.comp index 302a423..4ad7ab4 100644 --- a/client/shader/string.comp +++ b/client/shader/string.comp @@ -14,13 +14,13 @@ void main() { vec2 pen = vec2(0.0, 0.0); for(uint i = 0; i < string.len; i++) { - uint code = pc.layer.codes.c[string.offset + i]; + uint code = (pc.layer.codes.c[(string.offset + i)/4] >> ((string.offset + i) % 4)*8) & 0xFF; Symbol symbol = font.symbols.s[code]; pc.layer.drawables.d[buffer_pos + i].pos = string.pos + pen; pen += string.size*symbol.advance; pc.layer.drawables.d[buffer_pos + i].size = vec2(string.size, string.size); pc.layer.drawables.d[buffer_pos + i].color = string.color; - pc.layer.drawables.d[buffer_pos + i].var1 = pc.layer.codes.c[string.offset + i]; + pc.layer.drawables.d[buffer_pos + i].var1 = code; pc.layer.drawables.d[buffer_pos + i].var2 = string.font; pc.layer.drawables.d[buffer_pos + i].type = 1; } diff --git a/client/src/hex.c b/client/src/hex.c index ebc6dda..9d52eee 100644 --- a/client/src/hex.c +++ b/client/src/hex.c @@ -732,20 +732,12 @@ VkResult set_hex_region(HexRegion* region, HexContext* hex, RenderContext* gpu) return VK_ERROR_UNKNOWN; } - VkResult result; - VK_RESULT(add_transfer( + return add_transfer( ®ion->data.hexes, region->region, offsetof(GPUHexRegion, hexes), sizeof(GPUHex)*REGION_HEX_COUNT, gpu->current_frame, - gpu)); - - return add_transfers( - ®ion->address, - hex->context, - offsetof(GPUHexContext, regions) + sizeof(VkDeviceAddress)*index, - sizeof(VkDeviceAddress), gpu); } @@ -792,7 +784,12 @@ VkResult allocate_hex_region( (*region)->address = buffer_address(gpu->device, (*region)->region); - return VK_SUCCESS; + return add_transfers( + &(*region)->address, + hex->context, + offsetof(GPUHexContext, regions) + sizeof(VkDeviceAddress)*i, + sizeof(VkDeviceAddress), + gpu); } bool ray_hex_intersect( diff --git a/client/src/main.c b/client/src/main.c index 0a3ddaf..a9b6ebf 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -1,4 +1,5 @@ #include "GLFW/glfw3.h" +#include #define CGLM_PRINT_PRECISION 10 #define CGLM_DEFINE_PRINTS 1 #include "ui.h" @@ -41,6 +42,9 @@ typedef struct ClientContextStruct { float cur_spin_speed; float zoom_speed; float move_speed; + + uint32_t selected_region; + uint32_t last_selected_region; } ClientContext; void* network_thread(void* data) { @@ -79,42 +83,101 @@ VkResult add_hex_region(ClientContext* context) { return VK_SUCCESS; } -VkResult main_thread(ClientContext* context) { - VkResult result; +char region_info_strs[][20] = { + "Region XXXX", + "Q: XXXX", + "R: XXXX", + "Y: XXXX", +}; + +uint32_t region_info_str_off[] = { + 0, + 11, + 18, + 25, +}; + +VkResult region_info_ui(ClientContext* context) { GPUString strings[] = { { - .pos = {0, 32}, + .pos = {0, 33}, + .color = {1, 1, 1, 1}, + .size = 32, + .offset = region_info_str_off[0], + .length = strlen(region_info_strs[0]), + .font = 0, + }, + { + .pos = {0, 33 + 1*40}, + .color = {1, 1, 1, 1}, .size = 32, - .color = {1.0, 1.0, 1.0, 1.0}, - .offset = 0, - .length = 0, + .offset = region_info_str_off[1], + .length = strlen(region_info_strs[1]), + .font = 0, + }, + { + .pos = {0, 33 + 2*40}, + .color = {1, 1, 1, 1}, + .size = 32, + .offset = region_info_str_off[2], + .length = strlen(region_info_strs[2]), + .font = 0, + }, + { + .pos = {0, 33 + 3*40}, + .color = {1, 1, 1, 1}, + .size = 32, + .offset = region_info_str_off[3], + .length = strlen(region_info_strs[3]), .font = 0, }, }; - GPUDrawable drawables[] = {}; + uint32_t codes[43/4]; + VkResult result; + VK_RESULT(map_string(region_info_strs[0], codes, region_info_str_off[0], 0, context->ui)); + VK_RESULT(map_string(region_info_strs[1], codes, region_info_str_off[1], 0, context->ui)); + VK_RESULT(map_string(region_info_strs[2], codes, region_info_str_off[2], 0, context->ui)); + VK_RESULT(map_string(region_info_strs[3], codes, region_info_str_off[3], 0, context->ui)); + + GPUDrawable drawables[] = { + { + .pos = {0, 0}, + .size = {225, 155}, + .color = {0.4, 0.4, 0.4, 0.4}, + }, + }; LayerInput layer = { .strings = strings, .num_strings = sizeof(strings)/sizeof(GPUString), - .max_codes = 50, - + .max_strings = sizeof(strings)/sizeof(GPUString) + 4, + .codes = codes, + .num_codes = sizeof(codes)/sizeof(uint32_t), + .max_codes = sizeof(codes)/sizeof(uint32_t) + 100, .drawables = drawables, .num_drawables = sizeof(drawables)/sizeof(GPUDrawable), }; - ContainerInput container = { - .id = 1, - .size = {WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT}, - .layer_count = 1, + ContainerInput region_info = { + .id = 0x01, + .size = {225, 155}, + .offset = {0, 0}, + .anchor = ANCHOR_TOP_RIGHT, .layers = &layer, + .layer_count = 1, }; - create_container(&container, context->render, context->ui); + return create_container(®ion_info, context->render, context->ui); +} + +VkResult main_thread(ClientContext* context) { + VkResult result; + + VK_RESULT(region_info_ui(context)); // - int frame = 0; double last_frame_time = 0; while(glfwWindowShouldClose(context->window) == 0) { double frame_time = glfwGetTime(); @@ -128,16 +191,68 @@ VkResult main_thread(ClientContext* context) { context->cur_spin[1] = 0; glfwPollEvents(); + + if(context->selected_region != context->last_selected_region) { + context->last_selected_region = context->selected_region; + + + HexRegion* selected_region = context->hex->regions[context->selected_region]; + snprintf(region_info_strs[0], + sizeof(region_info_strs[0]), + "Region %4d", context->selected_region); + VK_RESULT(update_ui_string(region_info_strs[0], 0, 0, 0, context->ui, context->render)); + + if(selected_region == NULL) { + snprintf( + region_info_strs[1], + sizeof(region_info_strs[1]), + ""); + VK_RESULT(update_ui_string(region_info_strs[1], 0, 0, 1, context->ui, context->render)); + + snprintf( + region_info_strs[2], + sizeof(region_info_strs[2]), + ""); + VK_RESULT(update_ui_string(region_info_strs[2], 0, 0, 2, context->ui, context->render)); + + snprintf( + region_info_strs[3], + sizeof(region_info_strs[3]), + ""); + VK_RESULT(update_ui_string(region_info_strs[3], 0, 0, 3, context->ui, context->render)); + } else { + snprintf( + region_info_strs[1], + sizeof(region_info_strs[1]), + "Q: %4d", selected_region->data.q); + VK_RESULT(update_ui_string(region_info_strs[1], 0, 0, 1, context->ui, context->render)); + + snprintf( + region_info_strs[2], + sizeof(region_info_strs[2]), + "R: %4d", selected_region->data.r); + VK_RESULT(update_ui_string(region_info_strs[2], 0, 0, 2, context->ui, context->render)); + + snprintf( + region_info_strs[3], + sizeof(region_info_strs[3]), + "Y: %4d", selected_region->data.y); + VK_RESULT(update_ui_string(region_info_strs[3], 0, 0, 3, context->ui, context->render)); + } + + } + if((context->key_spin[0] != 0 || context->key_spin[1] != 0 || context->velocity[0] != 0 || context->velocity[1] != 0 || context->velocity[2] != 0 || context->zoom != 0 || context->cur_spin[0] != 0 || context->cur_spin[1] != 0 || - context->render->framebuffer_recreated == true) && frame > 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->key_spin[0]*delta_time*context->key_spin_speed; @@ -183,7 +298,6 @@ VkResult main_thread(ClientContext* context) { fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); glfwDestroyWindow(context->window); } - frame += 1; last_frame_time = frame_time; } @@ -272,10 +386,27 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod break; case GLFW_KEY_EQUAL: - if(action == GLFW_RELEASE) { + if(action == GLFW_PRESS) { add_hex_region(context); } break; + + case GLFW_KEY_LEFT_BRACKET: + if(action == GLFW_PRESS) { + context->selected_region -= 1; + if(context->selected_region > MAX_LOADED_REGIONS) { + context->selected_region = MAX_LOADED_REGIONS; + } + } + break; + case GLFW_KEY_RIGHT_BRACKET: + if(action == GLFW_PRESS) { + context->selected_region += 1; + if(context->selected_region > MAX_LOADED_REGIONS) { + context->selected_region = 0; + } + } + break; } } @@ -374,6 +505,9 @@ int main() { .cur_spin_speed = 1.0, .zoom_speed = 1.0, .move_speed = 0.1, + + .selected_region = MAX_LOADED_REGIONS, + .last_selected_region = 0, }; if(context.window == NULL || context.render == NULL || context.ui == NULL || context.hex == NULL) { return VK_ERROR_OUT_OF_HOST_MEMORY; diff --git a/client/src/ui.c b/client/src/ui.c index 58d04ed..0da0b74 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -705,12 +705,23 @@ VkResult load_font( .usage = VMA_MEMORY_USAGE_GPU_ONLY, }; - VK_RESULT(vmaCreateImage(gpu->allocator, &image_info, &image_memory_info, &context->fonts[index].image, &context->fonts[index].image_memory, NULL)); + VK_RESULT(vmaCreateImage( + gpu->allocator, + &image_info, + &image_memory_info, + &context->fonts[index].image, + &context->fonts[index].image_memory, + NULL)); VkBuffer transfer; VmaAllocation transfer_memory; void* mapped; - VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(GPUFont) + image_size*info.num_symbols + sizeof(GPUSymbol)*info.num_symbols, &transfer, &transfer_memory, &mapped)); + VK_RESULT(create_transfer_buffer( + gpu->allocator, + sizeof(GPUFont) + image_size*info.num_symbols + sizeof(GPUSymbol)*info.num_symbols, + &transfer, + &transfer_memory, + &mapped)); info.symbol_list = buffer_address(gpu->device, context->fonts[index].symbols); @@ -722,8 +733,19 @@ VkResult load_font( free(symbols); VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool); - command_copy_buffer(command_buffer, transfer, context->font_infos, image_size*info.num_symbols, index*sizeof(GPUFont), sizeof(GPUFont)); - command_copy_buffer(command_buffer, transfer, context->fonts[index].symbols, image_size*info.num_symbols + sizeof(GPUFont), 0, sizeof(GPUSymbol)*info.num_symbols); + command_copy_buffer( + command_buffer, + transfer, + context->font_infos, + image_size*info.num_symbols, + index*sizeof(GPUFont), + sizeof(GPUFont)); + command_copy_buffer(command_buffer, + transfer, + context->fonts[index].symbols, + image_size*info.num_symbols + sizeof(GPUFont), + 0, + sizeof(GPUSymbol)*info.num_symbols); VkImageMemoryBarrier first_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -1002,6 +1024,24 @@ VkResult create_ui_descriptor( return VK_SUCCESS; } +VkResult update_ui_context_resolution( + UIContext* ui, + RenderContext* gpu) { + ui->data.screen[0] = gpu->window_scale[0] / gpu->swapchain_extent.width; + ui->data.screen[1] = gpu->window_scale[1] / gpu->swapchain_extent.height; + ui->data.extent[0] = gpu->swapchain_extent.width / gpu->window_scale[0]; + ui->data.extent[1] = gpu->swapchain_extent.height / gpu->window_scale[1]; + ui->data.scale[0] = gpu->window_scale[0]; + ui->data.scale[1] = gpu->window_scale[1]; + + return add_transfer( + &ui->data.screen[0], + ui->context, + offsetof(GPUUIContext, screen), + sizeof(GPUUIContext) - offsetof(GPUUIContext, screen), + gpu->current_frame, gpu); +} + VkResult create_ui_context( uint32_t max_fonts, uint32_t max_textures, @@ -1015,14 +1055,18 @@ VkResult create_ui_context( return VK_ERROR_UNKNOWN; } - VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUUIContext), &context->context, &context->context_memory)); - VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(GPUFont)*max_fonts, &context->font_infos, &context->font_infos_memory)); - - VkBuffer transfer; - VmaAllocation transfer_context; - UIContext* mapped; - - VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(UIContext), &transfer, &transfer_context, (void**)&mapped)); + VK_RESULT(create_storage_buffer( + gpu->allocator, + 0, + sizeof(GPUUIContext), + &context->context, + &context->context_memory)); + VK_RESULT(create_storage_buffer( + gpu->allocator, + 0, + sizeof(GPUFont)*max_fonts, + &context->font_infos, + &context->font_infos_memory)); context->data.font_infos = buffer_address(gpu->device, context->font_infos); context->data.screen[0] = gpu->window_scale[0] / gpu->swapchain_extent.width; @@ -1031,17 +1075,36 @@ VkResult create_ui_context( context->data.extent[1] = gpu->swapchain_extent.height / gpu->window_scale[1]; context->data.scale[0] = gpu->window_scale[0]; context->data.scale[1] = gpu->window_scale[1]; - memcpy(mapped, &context->data, sizeof(GPUUIContext)); - VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool); - command_copy_buffer(command_buffer, transfer, context->context, 0, 0, sizeof(GPUUIContext)); - VK_RESULT(command_end_single(gpu->device, command_buffer, gpu->transfer_pool, gpu->transfer_queue)); - destroy_transfer_buffer(gpu->allocator, transfer, transfer_context); + VK_RESULT(add_transfer( + &context->data, + context->context, + 0, + sizeof(GPUUIContext), + gpu->current_frame, + gpu)); context->address = buffer_address(gpu->device, context->context); - VK_RESULT(create_ui_descriptor(gpu->device, max_fonts, max_textures, &context->samplers_layout, &context->textures_layout, &context->samplers, &context->textures, &context->font_samplers, &context->font_textures, &context->fonts_pool, &context->textures_pool)); - - VK_RESULT(create_ui_pipeline(gpu->device, gpu->render_pass, context->samplers_layout, context->textures_layout, &context->pipeline, &context->string_pipeline)); + VK_RESULT(create_ui_descriptor( + gpu->device, + max_fonts, + max_textures, + &context->samplers_layout, + &context->textures_layout, + &context->samplers, + &context->textures, + &context->font_samplers, + &context->font_textures, + &context->fonts_pool, + &context->textures_pool)); + + VK_RESULT(create_ui_pipeline( + gpu->device, + gpu->render_pass, + context->samplers_layout, + context->textures_layout, + &context->pipeline, + &context->string_pipeline)); context->max_textures = max_textures; context->max_fonts = max_fonts; @@ -1066,6 +1129,7 @@ VkResult map_string( uint32_t font, UIContext* context) { size_t i = 0; + memset((uint8_t*)buffer + offset, 0, strlen(text)); while(text[i] != '\0') { uint32_t mapped = 0xFFFFFFFF; for(uint32_t j = 0; j < context->fonts[font].num_symbols; j++) { @@ -1077,9 +1141,45 @@ VkResult map_string( if(mapped == 0xFFFFFFFF) { return VK_ERROR_UNKNOWN; } - buffer[i + offset] = mapped; + buffer[(i + offset)/4] += mapped << ((i + offset) % 4)*8; i += 1; } return VK_SUCCESS; } + +VkResult update_ui_string( + char* string, + uint32_t container_index, + uint32_t layer_index, + uint32_t string_index, + UIContext* ui, + RenderContext* gpu) { + VkResult result; + Container* container = &ui->containers[container_index]; + Layer* layer = &container->layers[layer_index]; + + layer->strings_buffer[string_index].length = strlen(string); + if(strlen(string) > 0) { + VK_RESULT(map_string( + string, + layer->codes_buffer, + layer->strings_buffer[string_index].offset, + layer->strings_buffer[string_index].font, + ui)); + VK_RESULT(add_transfers( + (uint8_t*)layer->codes_buffer + layer->strings_buffer[string_index].offset, + layer->codes, + layer->strings_buffer[string_index].offset, + strlen(string), + gpu)); + } + VK_RESULT(add_transfers( + &layer->strings_buffer[string_index].length, + layer->strings, + sizeof(GPUString)*string_index + offsetof(GPUString, length), + sizeof(uint32_t), + gpu)); + + return VK_SUCCESS; +}