|  |  |  | @ -1,4 +1,5 @@ | 
		
	
		
			
				|  |  |  |  | #include "GLFW/glfw3.h" | 
		
	
		
			
				|  |  |  |  | #include "cglm/cam.h" | 
		
	
		
			
				|  |  |  |  | #include "cglm/mat4.h" | 
		
	
		
			
				|  |  |  |  | #include "ui.h" | 
		
	
		
			
				|  |  |  |  | #include "gpu.h" | 
		
	
	
		
			
				
					|  |  |  | @ -10,6 +11,7 @@ | 
		
	
		
			
				|  |  |  |  | #include "vulkan/vk_enum_string_helper.h" | 
		
	
		
			
				|  |  |  |  | #include "vulkan/vulkan_core.h" | 
		
	
		
			
				|  |  |  |  | #include "pthread.h" | 
		
	
		
			
				|  |  |  |  | #include <math.h> | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | typedef struct ClientContextStruct { | 
		
	
		
			
				|  |  |  |  |   GLFWwindow* window; | 
		
	
	
		
			
				
					|  |  |  | @ -19,12 +21,21 @@ typedef struct ClientContextStruct { | 
		
	
		
			
				|  |  |  |  |   uint32_t clicked_container; | 
		
	
		
			
				|  |  |  |  |   uint32_t clicked_element; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vec3 pos; | 
		
	
		
			
				|  |  |  |  |   vec4 rot; | 
		
	
		
			
				|  |  |  |  |   double delta_time; | 
		
	
		
			
				|  |  |  |  |   VkBuffer hex_context; | 
		
	
		
			
				|  |  |  |  |   VmaAllocation hex_context_memory; | 
		
	
		
			
				|  |  |  |  |   GPUHexContext hex; | 
		
	
		
			
				|  |  |  |  |   vec2    cursor; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vec3    position; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   vec2    rotation; | 
		
	
		
			
				|  |  |  |  |   int32_t key_spin[2]; | 
		
	
		
			
				|  |  |  |  |   vec2    cur_spin; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   double  distance; | 
		
	
		
			
				|  |  |  |  |   int32_t zoom; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   bool    camera_mode; | 
		
	
		
			
				|  |  |  |  |   float   key_spin_speed; | 
		
	
		
			
				|  |  |  |  |   float   cur_spin_speed; | 
		
	
		
			
				|  |  |  |  |   float   zoom_speed; | 
		
	
		
			
				|  |  |  |  | } ClientContext; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void* network_thread(void* data) { | 
		
	
	
		
			
				
					|  |  |  | @ -34,6 +45,9 @@ void* network_thread(void* data) { | 
		
	
		
			
				|  |  |  |  |   return NULL; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | vec3 zero = {0, 0, 0}; | 
		
	
		
			
				|  |  |  |  | vec3 up = {0, 1, 0}; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -110,12 +124,31 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |         4*sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |         &context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_storage_buffer(context->render.allocator, 0, sizeof(GPUHexContext), &context->hex_context, &context->hex_context_memory)); | 
		
	
		
			
				|  |  |  |  |   VkDeviceAddress hex_context_address = buffer_address(context->render.device, context->hex_context); | 
		
	
		
			
				|  |  |  |  |   glm_ortho_default((float)context->render.swapchain_extent.width/(float)context->render.swapchain_extent.height, context->hex.proj); | 
		
	
		
			
				|  |  |  |  |   glm_translate_make(context->hex.view, context->pos); | 
		
	
		
			
				|  |  |  |  |   add_transfer(&context->hex, context->hex_context, 0, sizeof(GPUHexContext), 0, &context->render); | 
		
	
		
			
				|  |  |  |  |   add_transfer(&context->hex, context->hex_context, 0, sizeof(GPUHexContext), 1, &context->render); | 
		
	
		
			
				|  |  |  |  |   VkBuffer hex_context; | 
		
	
		
			
				|  |  |  |  |   VmaAllocation hex_context_memory; | 
		
	
		
			
				|  |  |  |  |   GPUHexContext hex; | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(create_storage_buffer(context->render.allocator, 0, sizeof(GPUHexContext), &hex_context, &hex_context_memory)); | 
		
	
		
			
				|  |  |  |  |   VkDeviceAddress hex_context_address = buffer_address(context->render.device, hex_context); | 
		
	
		
			
				|  |  |  |  |   glm_perspective(30.0, (float)context->render.swapchain_extent.width/(float)context->render.swapchain_extent.height, 0.01, 99.9, hex.proj); | 
		
	
		
			
				|  |  |  |  |   context->position[0] = 0; | 
		
	
		
			
				|  |  |  |  |   context->position[1] = 0; | 
		
	
		
			
				|  |  |  |  |   context->position[2] = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   context->rotation[0] = 0; | 
		
	
		
			
				|  |  |  |  |   context->rotation[1] = 0; | 
		
	
		
			
				|  |  |  |  |   context->cur_spin[0] = 0; | 
		
	
		
			
				|  |  |  |  |   context->cur_spin[1] = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   context->key_spin[0] = 0; | 
		
	
		
			
				|  |  |  |  |   context->key_spin[1] = 0; | 
		
	
		
			
				|  |  |  |  |   context->cur_spin[0] = 0; | 
		
	
		
			
				|  |  |  |  |   context->cur_spin[1] = 0; | 
		
	
		
			
				|  |  |  |  |   context->distance = 1; | 
		
	
		
			
				|  |  |  |  |   context->zoom = 0; | 
		
	
		
			
				|  |  |  |  |   context->camera_mode = false; | 
		
	
		
			
				|  |  |  |  |   context->key_spin_speed = 1.0; | 
		
	
		
			
				|  |  |  |  |   context->cur_spin_speed = 1.0; | 
		
	
		
			
				|  |  |  |  |   context->zoom_speed = 1.0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   //
 | 
		
	
		
			
				|  |  |  |  |   uint32_t* mapped_codes = context->ui.containers[0].layers[0].codes_buffer; | 
		
	
	
		
			
				
					|  |  |  | @ -126,13 +159,50 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   double last_frame_time = glfwGetTime(); | 
		
	
		
			
				|  |  |  |  |   while(glfwWindowShouldClose(context->window) == 0) { | 
		
	
		
			
				|  |  |  |  |     double frame_time = glfwGetTime(); | 
		
	
		
			
				|  |  |  |  |     context->delta_time = (frame_time - last_frame_time); | 
		
	
		
			
				|  |  |  |  |     double delta_time = (frame_time - last_frame_time); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     context->clicked_element   = 0x00000000; | 
		
	
		
			
				|  |  |  |  |     context->clicked_container = 0x00000000; | 
		
	
		
			
				|  |  |  |  |     context->zoom = 0; | 
		
	
		
			
				|  |  |  |  |     context->cur_spin[0] = 0; | 
		
	
		
			
				|  |  |  |  |     context->cur_spin[1] = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     glfwPollEvents(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     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->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; | 
		
	
		
			
				|  |  |  |  |       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->key_spin[1]*delta_time*context->key_spin_speed; | 
		
	
		
			
				|  |  |  |  |       context->rotation[1] += (float)context->cur_spin[1]*delta_time*context->cur_spin_speed; | 
		
	
		
			
				|  |  |  |  |       if(context->rotation[1] > M_PI/2) { | 
		
	
		
			
				|  |  |  |  |         context->rotation[1] = M_PI/2; | 
		
	
		
			
				|  |  |  |  |       } else if(context->rotation[1] < 0) { | 
		
	
		
			
				|  |  |  |  |         context->rotation[1] = 0; | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       context->distance += context->zoom*delta_time*context->zoom_speed; | 
		
	
		
			
				|  |  |  |  |       if(context->distance < 1) { | 
		
	
		
			
				|  |  |  |  |         context->distance = 1; | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       vec3 camera; | 
		
	
		
			
				|  |  |  |  |       camera[0] = context->position[0] + context->distance*cos(context->rotation[1])*cos(context->rotation[0]); | 
		
	
		
			
				|  |  |  |  |       camera[1] = context->position[1] + context->distance*sin(context->rotation[1]); | 
		
	
		
			
				|  |  |  |  |       camera[2] = context->position[2] + context->distance*cos(context->rotation[1])*sin(context->rotation[0]); | 
		
	
		
			
				|  |  |  |  |       glm_lookat(camera, context->position, up, hex.view); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       add_transfer(&hex, hex_context, 0, sizeof(GPUHexContext), (context->render.current_frame + 1) % MAX_FRAMES_IN_FLIGHT, &context->render); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     if(context->clicked_container != 0) { | 
		
	
		
			
				|  |  |  |  |       snprintf(str, 21, "Clicked: %d.%d", context->clicked_container, context->clicked_element); | 
		
	
		
			
				|  |  |  |  |       map_string(str, mapped_codes, 0, 0, &context->ui); | 
		
	
	
		
			
				
					|  |  |  | @ -166,11 +236,40 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |   (void)window; | 
		
	
		
			
				|  |  |  |  |   (void)key; | 
		
	
		
			
				|  |  |  |  |   ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); | 
		
	
		
			
				|  |  |  |  |   (void)scancode; | 
		
	
		
			
				|  |  |  |  |   (void)action; | 
		
	
		
			
				|  |  |  |  |   (void)mods; | 
		
	
		
			
				|  |  |  |  |   switch(key) { | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_A: | 
		
	
		
			
				|  |  |  |  |     if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[0] -= 1; | 
		
	
		
			
				|  |  |  |  |     } else if(action == GLFW_RELEASE) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[0] += 1; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_D: | 
		
	
		
			
				|  |  |  |  |     if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[0] += 1; | 
		
	
		
			
				|  |  |  |  |     } else if(action == GLFW_RELEASE) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[0] -= 1; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_W: | 
		
	
		
			
				|  |  |  |  |     if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[1] += 1; | 
		
	
		
			
				|  |  |  |  |     } else if(action == GLFW_RELEASE) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[1] -= 1; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_S: | 
		
	
		
			
				|  |  |  |  |     if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[1] -= 1; | 
		
	
		
			
				|  |  |  |  |     } else if(action == GLFW_RELEASE) { | 
		
	
		
			
				|  |  |  |  |       context->key_spin[1] += 1; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | bool contains(double* point, GPUContainer* container, GPUDrawable* rect) { | 
		
	
	
		
			
				
					|  |  |  | @ -193,11 +292,13 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) | 
		
	
		
			
				|  |  |  |  |   glfwGetCursorPos(window, &cursor[0], &cursor[1]); | 
		
	
		
			
				|  |  |  |  |   switch(button) { | 
		
	
		
			
				|  |  |  |  |   // Handle camera hover
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_MOUSE_BUTTON_MIDDLE: | 
		
	
		
			
				|  |  |  |  |   case GLFW_MOUSE_BUTTON_RIGHT: | 
		
	
		
			
				|  |  |  |  |     if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |       glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); | 
		
	
		
			
				|  |  |  |  |       context->camera_mode = true; | 
		
	
		
			
				|  |  |  |  |     } else { | 
		
	
		
			
				|  |  |  |  |       glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); | 
		
	
		
			
				|  |  |  |  |       context->camera_mode = false; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_MOUSE_BUTTON_LEFT: | 
		
	
	
		
			
				
					|  |  |  | @ -225,23 +326,24 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) | 
		
	
		
			
				|  |  |  |  |       // 3. Based on what was clicked, start the mouse click animation at the target area
 | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_MOUSE_BUTTON_RIGHT: | 
		
	
		
			
				|  |  |  |  |     if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { | 
		
	
		
			
				|  |  |  |  |   (void)window; | 
		
	
		
			
				|  |  |  |  |   ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); | 
		
	
		
			
				|  |  |  |  |   (void)xoffset; | 
		
	
		
			
				|  |  |  |  |   (void)yoffset; | 
		
	
		
			
				|  |  |  |  |   context->zoom = -yoffset;   | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { | 
		
	
		
			
				|  |  |  |  |   (void)window; | 
		
	
		
			
				|  |  |  |  |   (void)xpos; | 
		
	
		
			
				|  |  |  |  |   (void)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->cursor[0] = xpos; | 
		
	
		
			
				|  |  |  |  |     context->cursor[1] = ypos; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int main() { | 
		
	
	
		
			
				
					|  |  |  | 
 |