|  |  |  | @ -18,9 +18,9 @@ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | typedef struct ClientContextStruct { | 
		
	
		
			
				|  |  |  |  |   GLFWwindow* window; | 
		
	
		
			
				|  |  |  |  |   RenderContext render; | 
		
	
		
			
				|  |  |  |  |   UIContext ui; | 
		
	
		
			
				|  |  |  |  |   HexContext hex; | 
		
	
		
			
				|  |  |  |  |   RenderContext* render; | 
		
	
		
			
				|  |  |  |  |   UIContext* ui; | 
		
	
		
			
				|  |  |  |  |   HexContext* hex; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   uint32_t clicked_container; | 
		
	
		
			
				|  |  |  |  |   uint32_t clicked_element; | 
		
	
	
		
			
				
					|  |  |  | @ -86,7 +86,7 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |     .layers = &layer, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   create_container(&container, &context->render, &context->ui); | 
		
	
		
			
				|  |  |  |  |   create_container(&container, context->render, context->ui); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   HexRegion* regions[MAX_LOADED_REGIONS]; | 
		
	
		
			
				|  |  |  |  |   uint32_t colors[] = { | 
		
	
	
		
			
				
					|  |  |  | @ -98,7 +98,7 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   uint32_t region = 0; | 
		
	
		
			
				|  |  |  |  |   for(int32_t q = -10; q < 10; q++) { | 
		
	
		
			
				|  |  |  |  |     for(int32_t r = -10; r < 10; r++) { | 
		
	
		
			
				|  |  |  |  |       VK_RESULT(create_hex_region(q, r, ®ions[region], &context->hex, &context->render)); | 
		
	
		
			
				|  |  |  |  |       VK_RESULT(create_hex_region(q, r, ®ions[region], context->hex, context->render)); | 
		
	
		
			
				|  |  |  |  |       for(uint32_t i = 0; i < REGION_HEX_COUNT; i++) { | 
		
	
		
			
				|  |  |  |  |         for(uint32_t h = 0; h < 6; h++) { | 
		
	
		
			
				|  |  |  |  |           regions[region]->data[i].color[h] = colors[(q+r+50) % (sizeof(colors)/sizeof(uint32_t))]; | 
		
	
	
		
			
				
					|  |  |  | @ -106,7 +106,7 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         regions[region]->data[i].color[6] = colors[(q+r+50) % (sizeof(colors)/sizeof(uint32_t))]; | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |       VK_RESULT(add_transfer(®ions[region]->data, regions[region]->region, offsetof(GPUHexRegion, hexes), sizeof(GPUHex)*REGION_HEX_COUNT, 0, &context->render)); | 
		
	
		
			
				|  |  |  |  |       VK_RESULT(add_transfer(®ions[region]->data, regions[region]->region, offsetof(GPUHexRegion, hexes), sizeof(GPUHex)*REGION_HEX_COUNT, 0, context->render)); | 
		
	
		
			
				|  |  |  |  |       region++; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
	
		
			
				
					|  |  |  | @ -132,8 +132,8 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   context->zoom_speed = 1.0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   //
 | 
		
	
		
			
				|  |  |  |  |   uint32_t* mapped_codes = context->ui.containers[0].layers[0].codes_buffer; | 
		
	
		
			
				|  |  |  |  |   GPUString* mapped_string = context->ui.containers[0].layers[0].strings_buffer; | 
		
	
		
			
				|  |  |  |  |   uint32_t* mapped_codes = context->ui->containers[0].layers[0].codes_buffer; | 
		
	
		
			
				|  |  |  |  |   GPUString* mapped_string = context->ui->containers[0].layers[0].strings_buffer; | 
		
	
		
			
				|  |  |  |  |   char str[51]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   int frame = 0; | 
		
	
	
		
			
				
					|  |  |  | @ -155,9 +155,9 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |     if((context->key_spin[0] != 0 || context->key_spin[1] != 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) && frame > 0) { | 
		
	
		
			
				|  |  |  |  |       // signal it as handled
 | 
		
	
		
			
				|  |  |  |  |       context->render.framebuffer_recreated = false; | 
		
	
		
			
				|  |  |  |  |       context->render->framebuffer_recreated = false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       context->rotation[0] += (float)context->key_spin[0]*delta_time*context->key_spin_speed;  | 
		
	
		
			
				|  |  |  |  |       context->rotation[0] += (float)context->cur_spin[0]*delta_time*context->cur_spin_speed; | 
		
	
	
		
			
				
					|  |  |  | @ -193,33 +193,33 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |       hex_forward[0] = 0; | 
		
	
		
			
				|  |  |  |  |       hex_forward[1] = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       glm_lookat(camera, context->position, up, context->hex.data.view); | 
		
	
		
			
				|  |  |  |  |       add_transfer(&context->hex.data, context->hex.context, 0, 2*sizeof(mat4), context->render.current_frame, &context->render); | 
		
	
		
			
				|  |  |  |  |       add_transfer(hex_pos, context->hex.context, offsetof(GPUHexContext, camera), sizeof(vec2), context->render.current_frame, &context->render); | 
		
	
		
			
				|  |  |  |  |       add_transfer(hex_forward, context->hex.context, offsetof(GPUHexContext, forward), sizeof(vec2), context->render.current_frame, &context->render); | 
		
	
		
			
				|  |  |  |  |       glm_lookat(camera, context->position, up, context->hex->data.view); | 
		
	
		
			
				|  |  |  |  |       add_transfer(&context->hex->data, context->hex->context, 0, 2*sizeof(mat4), context->render->current_frame, context->render); | 
		
	
		
			
				|  |  |  |  |       add_transfer(hex_pos, context->hex->context, offsetof(GPUHexContext, camera), sizeof(vec2), context->render->current_frame, context->render); | 
		
	
		
			
				|  |  |  |  |       add_transfer(hex_forward, context->hex->context, offsetof(GPUHexContext, forward), sizeof(vec2), context->render->current_frame, context->render); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     if(context->clicked_hex[0] != 0 || context->clicked_hex[1] != 0) { | 
		
	
		
			
				|  |  |  |  |       snprintf(str, 50, "Clicked: (%d,%d)", context->clicked_hex[0], context->clicked_hex[1]); | 
		
	
		
			
				|  |  |  |  |       map_string(str, mapped_codes, 0, 0, &context->ui); | 
		
	
		
			
				|  |  |  |  |       map_string(str, mapped_codes, 0, 0, context->ui); | 
		
	
		
			
				|  |  |  |  |       VK_RESULT(add_transfers( | 
		
	
		
			
				|  |  |  |  |             context->ui.containers[0].layers[0].codes_buffer, | 
		
	
		
			
				|  |  |  |  |             context->ui.containers[0].layers[0].codes, | 
		
	
		
			
				|  |  |  |  |             context->ui->containers[0].layers[0].codes_buffer, | 
		
	
		
			
				|  |  |  |  |             context->ui->containers[0].layers[0].codes, | 
		
	
		
			
				|  |  |  |  |             0, | 
		
	
		
			
				|  |  |  |  |             strlen(str)*sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |             &context->render)); | 
		
	
		
			
				|  |  |  |  |             context->render)); | 
		
	
		
			
				|  |  |  |  |       mapped_string->length = strlen(str); | 
		
	
		
			
				|  |  |  |  |       VK_RESULT(add_transfers( | 
		
	
		
			
				|  |  |  |  |             &context->ui.containers[0].layers[0].strings_buffer[0].length, | 
		
	
		
			
				|  |  |  |  |             context->ui.containers[0].layers[0].strings, | 
		
	
		
			
				|  |  |  |  |             &context->ui->containers[0].layers[0].strings_buffer[0].length, | 
		
	
		
			
				|  |  |  |  |             context->ui->containers[0].layers[0].strings, | 
		
	
		
			
				|  |  |  |  |             offsetof(GPUString, length), | 
		
	
		
			
				|  |  |  |  |             sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |             &context->render)); | 
		
	
		
			
				|  |  |  |  |             context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     //
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     VkResult result = draw_frame(&context->render, &context->ui, &context->hex, frame_time); | 
		
	
		
			
				|  |  |  |  |     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); | 
		
	
	
		
			
				
					|  |  |  | @ -300,19 +300,19 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_MOUSE_BUTTON_LEFT: | 
		
	
		
			
				|  |  |  |  |     if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |       for(int32_t c = context->ui.max_containers - 1; c >= 0; c--) { | 
		
	
		
			
				|  |  |  |  |         if(context->ui.containers[c].id == 0x00000000) { | 
		
	
		
			
				|  |  |  |  |       for(int32_t c = context->ui->max_containers - 1; c >= 0; c--) { | 
		
	
		
			
				|  |  |  |  |         if(context->ui->containers[c].id == 0x00000000) { | 
		
	
		
			
				|  |  |  |  |           continue; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         for(uint32_t l = 0; l < context->ui.containers[c].layer_count; l++) { | 
		
	
		
			
				|  |  |  |  |           for(uint32_t d = 0; d < context->ui.containers[c].layers[l].data.num_drawables; d++) { | 
		
	
		
			
				|  |  |  |  |             if(context->ui.containers[c].layers[l].drawables_buffer[d].id == 0x00000000) { | 
		
	
		
			
				|  |  |  |  |         for(uint32_t l = 0; l < context->ui->containers[c].layer_count; l++) { | 
		
	
		
			
				|  |  |  |  |           for(uint32_t d = 0; d < context->ui->containers[c].layers[l].data.num_drawables; d++) { | 
		
	
		
			
				|  |  |  |  |             if(context->ui->containers[c].layers[l].drawables_buffer[d].id == 0x00000000) { | 
		
	
		
			
				|  |  |  |  |               continue; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             if(contains(cursor, &context->ui.containers[c].data, &context->ui.containers[c].layers[l].drawables_buffer[d])) { | 
		
	
		
			
				|  |  |  |  |               context->clicked_container = context->ui.containers[c].id; | 
		
	
		
			
				|  |  |  |  |               context->clicked_element = context->ui.containers[c].layers[l].drawables_buffer[d].id; | 
		
	
		
			
				|  |  |  |  |             if(contains(cursor, &context->ui->containers[c].data, &context->ui->containers[c].layers[l].drawables_buffer[d])) { | 
		
	
		
			
				|  |  |  |  |               context->clicked_container = context->ui->containers[c].id; | 
		
	
		
			
				|  |  |  |  |               context->clicked_element = context->ui->containers[c].layers[l].drawables_buffer[d].id; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |           } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -335,8 +335,8 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { | 
		
	
		
			
				|  |  |  |  | void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { | 
		
	
		
			
				|  |  |  |  |   ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); | 
		
	
		
			
				|  |  |  |  |   if(context->camera_mode == true) { | 
		
	
		
			
				|  |  |  |  |     context->cur_spin[0] = (xpos - context->cursor[0])/context->render.swapchain_extent.width*-100; | 
		
	
		
			
				|  |  |  |  |     context->cur_spin[1] = (ypos - context->cursor[1])/context->render.swapchain_extent.height*100; | 
		
	
		
			
				|  |  |  |  |     context->cur_spin[0] = (xpos - context->cursor[0])/context->render->swapchain_extent.width*-100; | 
		
	
		
			
				|  |  |  |  |     context->cur_spin[1] = (ypos - context->cursor[1])/context->render->swapchain_extent.height*100; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     context->cursor[0] = xpos; | 
		
	
		
			
				|  |  |  |  |     context->cursor[1] = ypos; | 
		
	
	
		
			
				
					|  |  |  | @ -344,10 +344,14 @@ void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int main() { | 
		
	
		
			
				|  |  |  |  |   ClientContext context = {}; | 
		
	
		
			
				|  |  |  |  |   context.window = init_window(); | 
		
	
		
			
				|  |  |  |  |   if(context.window == NULL) { | 
		
	
		
			
				|  |  |  |  |     return 1; | 
		
	
		
			
				|  |  |  |  |   ClientContext context = { | 
		
	
		
			
				|  |  |  |  |     .render = malloc(sizeof(RenderContext)), | 
		
	
		
			
				|  |  |  |  |     .ui = malloc(sizeof(UIContext)), | 
		
	
		
			
				|  |  |  |  |     .hex = malloc(sizeof(HexContext)), | 
		
	
		
			
				|  |  |  |  |     .window = init_window(), | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  |   if(context.window == NULL || context.render == NULL || context.ui == NULL || context.hex == NULL) { | 
		
	
		
			
				|  |  |  |  |     return VK_ERROR_OUT_OF_HOST_MEMORY; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   glfwSetWindowUserPointer(context.window, &context); | 
		
	
	
		
			
				
					|  |  |  | @ -358,11 +362,11 @@ int main() { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   int error; | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(init_vulkan(context.window, &context.render)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(init_vulkan(context.window, context.render)); | 
		
	
		
			
				|  |  |  |  |    | 
		
	
		
			
				|  |  |  |  |   // TODO: make # of fonts/textures/containers scaling, recreate GPU buffers as necessary
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_ui_context(10, 10, 10, &context.render, &context.ui)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_hex_context(&context.render, &context.hex)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_ui_context(10, 10, 10, context.render, context.ui)); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_hex_context(context.render, context.hex)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   pthread_t network_thread_handle; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | 
 |