|  |  |  | @ -1,6 +1,8 @@ | 
		
	
		
			
				|  |  |  |  | #include <stdio.h> | 
		
	
		
			
				|  |  |  |  | #include "hex.h" | 
		
	
		
			
				|  |  |  |  | #include "hsv.h" | 
		
	
		
			
				|  |  |  |  | #include "engine.h" | 
		
	
		
			
				|  |  |  |  | #include "vulkan/vulkan_core.h" | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #include <math.h> | 
		
	
		
			
				|  |  |  |  | #include <stdlib.h> | 
		
	
	
		
			
				
					|  |  |  | @ -8,7 +10,6 @@ | 
		
	
		
			
				|  |  |  |  | #define COLOR_PICK_CONTAINER_ID 0x03 | 
		
	
		
			
				|  |  |  |  | typedef struct EditorDataStruct {  | 
		
	
		
			
				|  |  |  |  |   uint32_t selected_region; | 
		
	
		
			
				|  |  |  |  |   uint32_t last_selected_region; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   uint32_t last_clicked_region; | 
		
	
		
			
				|  |  |  |  |   uint32_t last_clicked_hex; | 
		
	
	
		
			
				
					|  |  |  | @ -29,6 +30,35 @@ uint32_t hex_color(vec4 color) { | 
		
	
		
			
				|  |  |  |  |        + ((lrint(color[3]*255.0) & 0xFF) <<  0); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult set_vertex_height(float height, uint32_t region, uint32_t hex, uint32_t vertex, ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   if(vertex == 0) return VK_ERROR_VALIDATION_FAILED_EXT; | 
		
	
		
			
				|  |  |  |  |   context->hex.regions[region]->data.hexes[hex].height[vertex-1] = height;  | 
		
	
		
			
				|  |  |  |  |   return add_transfer( | 
		
	
		
			
				|  |  |  |  |       &context->hex.regions[region]->data.hexes[hex].height[vertex-1], | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[region]->region, | 
		
	
		
			
				|  |  |  |  |       offsetof(GPUHexRegion, hexes) | 
		
	
		
			
				|  |  |  |  |       + sizeof(GPUHex)*hex | 
		
	
		
			
				|  |  |  |  |       + offsetof(GPUHex, height) | 
		
	
		
			
				|  |  |  |  |       + sizeof(float)*(vertex-1), | 
		
	
		
			
				|  |  |  |  |       sizeof(float), | 
		
	
		
			
				|  |  |  |  |       context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |       &context->render); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | VkResult set_vertex_color(vec4 color, uint32_t region, uint32_t hex, uint32_t vertex, ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   context->hex.regions[region]->data.hexes[hex].color[vertex] = hex_color(color);  | 
		
	
		
			
				|  |  |  |  |   return add_transfer( | 
		
	
		
			
				|  |  |  |  |       &context->hex.regions[region]->data.hexes[hex].color[vertex], | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[region]->region, | 
		
	
		
			
				|  |  |  |  |       offsetof(GPUHexRegion, hexes) | 
		
	
		
			
				|  |  |  |  |       + sizeof(GPUHex)*hex | 
		
	
		
			
				|  |  |  |  |       + offsetof(GPUHex, color) | 
		
	
		
			
				|  |  |  |  |       + sizeof(uint32_t)*vertex, | 
		
	
		
			
				|  |  |  |  |       sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |       context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |       &context->render); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | uint32_t add_hex_region(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   HexRegion* region; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -834,12 +864,13 @@ VkResult update_region_info_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   EditorData* data = context->app_data; | 
		
	
		
			
				|  |  |  |  |   HexRegion* selected_region = context->hex.regions[data->selected_region]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   snprintf(temp, | 
		
	
		
			
				|  |  |  |  |       sizeof(temp), | 
		
	
		
			
				|  |  |  |  |       "Region %4d", data->selected_region); | 
		
	
		
			
				|  |  |  |  |   VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(selected_region == NULL) { | 
		
	
		
			
				|  |  |  |  |     snprintf(temp, | 
		
	
		
			
				|  |  |  |  |         sizeof(temp), | 
		
	
		
			
				|  |  |  |  |         ""); | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     snprintf( | 
		
	
		
			
				|  |  |  |  |         temp, | 
		
	
		
			
				|  |  |  |  |         sizeof(temp), | 
		
	
	
		
			
				
					|  |  |  | @ -858,16 +889,21 @@ VkResult update_region_info_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |         ""); | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(update_ui_string(temp, 0x01, 0, 3, &context->ui, &context->render)); | 
		
	
		
			
				|  |  |  |  |   } else { | 
		
	
		
			
				|  |  |  |  |     snprintf(temp, | 
		
	
		
			
				|  |  |  |  |         sizeof(temp), | 
		
	
		
			
				|  |  |  |  |         "Region %4d", data->selected_region); | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     snprintf( | 
		
	
		
			
				|  |  |  |  |         temp, | 
		
	
		
			
				|  |  |  |  |         sizeof(temp), | 
		
	
		
			
				|  |  |  |  |         "Q: %4d", selected_region->data.q); | 
		
	
		
			
				|  |  |  |  |         "Q: %4d", selected_region->data.position.q); | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(update_ui_string(temp, 0x01, 0, 1, &context->ui, &context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     snprintf( | 
		
	
		
			
				|  |  |  |  |         temp, | 
		
	
		
			
				|  |  |  |  |         sizeof(temp), | 
		
	
		
			
				|  |  |  |  |         "R: %4d", selected_region->data.r); | 
		
	
		
			
				|  |  |  |  |         "R: %4d", selected_region->data.position.r); | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(update_ui_string(temp, 0x01, 0, 2, &context->ui, &context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     snprintf( | 
		
	
	
		
			
				
					|  |  |  | @ -943,14 +979,12 @@ VkResult update_hex_info_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |         context->hex.data.clicked_hex); | 
		
	
		
			
				|  |  |  |  |     VK_RESULT(update_ui_string(temp, 0x02, 0, 0, &context->ui, &context->render)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     HexCoord hex_world; | 
		
	
		
			
				|  |  |  |  |     hex_qr(context->hex.data.clicked_hex, &hex_world); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     HexCoord region_coord = {region->data.q, region->data.r}; | 
		
	
		
			
				|  |  |  |  |      | 
		
	
		
			
				|  |  |  |  |     HexCoord region_coord = {region->data.position.q, region->data.position.r}; | 
		
	
		
			
				|  |  |  |  |     HexCoord region_world; | 
		
	
		
			
				|  |  |  |  |     region_qr(region_coord, ®ion_world); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     hex_add(region_world, &hex_world); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |     snprintf( | 
		
	
	
		
			
				
					|  |  |  | @ -1010,7 +1044,7 @@ VkResult update_hex_info_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | bool editor_key_callback(ClientContext* context, int key, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |   (void)mods; | 
		
	
		
			
				|  |  |  |  |   uint32_t start, next_region; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(action != GLFW_PRESS) return false; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -1020,28 +1054,59 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods) | 
		
	
		
			
				|  |  |  |  |   switch(key) { | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_EQUAL: | 
		
	
		
			
				|  |  |  |  |     data->selected_region = add_hex_region(context); | 
		
	
		
			
				|  |  |  |  |     update_region_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     update_hex_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_LEFT_BRACKET: | 
		
	
		
			
				|  |  |  |  |     data->selected_region -= 1; | 
		
	
		
			
				|  |  |  |  |     if(data->selected_region > MAX_LOADED_REGIONS) { | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_MINUS: | 
		
	
		
			
				|  |  |  |  |     free_hex_region(data->selected_region, &context->hex, &context->render); | 
		
	
		
			
				|  |  |  |  |     start = data->selected_region; | 
		
	
		
			
				|  |  |  |  |     next_region = start; | 
		
	
		
			
				|  |  |  |  |     do { | 
		
	
		
			
				|  |  |  |  |       next_region -= 1; | 
		
	
		
			
				|  |  |  |  |       if(next_region > MAX_LOADED_REGIONS) next_region = MAX_LOADED_REGIONS; | 
		
	
		
			
				|  |  |  |  |       if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break; | 
		
	
		
			
				|  |  |  |  |     } while(next_region != start); | 
		
	
		
			
				|  |  |  |  |     if(next_region == start) { | 
		
	
		
			
				|  |  |  |  |       data->selected_region = MAX_LOADED_REGIONS; | 
		
	
		
			
				|  |  |  |  |     } else { | 
		
	
		
			
				|  |  |  |  |       data->selected_region = next_region; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     update_region_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     update_hex_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_LEFT_BRACKET: | 
		
	
		
			
				|  |  |  |  |     start = data->selected_region; | 
		
	
		
			
				|  |  |  |  |     next_region = start; | 
		
	
		
			
				|  |  |  |  |     do { | 
		
	
		
			
				|  |  |  |  |       next_region -= 1; | 
		
	
		
			
				|  |  |  |  |       if(next_region > MAX_LOADED_REGIONS) next_region = MAX_LOADED_REGIONS; | 
		
	
		
			
				|  |  |  |  |       if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break; | 
		
	
		
			
				|  |  |  |  |     } while(next_region != start); | 
		
	
		
			
				|  |  |  |  |     data->selected_region = next_region; | 
		
	
		
			
				|  |  |  |  |     update_region_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_RIGHT_BRACKET: | 
		
	
		
			
				|  |  |  |  |     data->selected_region += 1; | 
		
	
		
			
				|  |  |  |  |     if(data->selected_region > MAX_LOADED_REGIONS) { | 
		
	
		
			
				|  |  |  |  |       data->selected_region = 0; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     start = data->selected_region; | 
		
	
		
			
				|  |  |  |  |     next_region = start; | 
		
	
		
			
				|  |  |  |  |     do { | 
		
	
		
			
				|  |  |  |  |       next_region += 1; | 
		
	
		
			
				|  |  |  |  |       if(next_region > MAX_LOADED_REGIONS) next_region = 0; | 
		
	
		
			
				|  |  |  |  |       if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break; | 
		
	
		
			
				|  |  |  |  |     } while(next_region != start); | 
		
	
		
			
				|  |  |  |  |     data->selected_region = next_region; | 
		
	
		
			
				|  |  |  |  |     update_region_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_I: | 
		
	
		
			
				|  |  |  |  |     if(context->hex.regions[data->selected_region] != NULL) { | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.q += 1; | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.position.q += 1; | 
		
	
		
			
				|  |  |  |  |       add_transfer( | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.q, | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.position, | 
		
	
		
			
				|  |  |  |  |           context->hex.regions[data->selected_region]->region, | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, q), | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, position), | 
		
	
		
			
				|  |  |  |  |           sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |           context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |           &context->render); | 
		
	
	
		
			
				
					|  |  |  | @ -1050,11 +1115,11 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods) | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_K: | 
		
	
		
			
				|  |  |  |  |     if(context->hex.regions[data->selected_region] != NULL) { | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.q -= 1; | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.position.q -= 1; | 
		
	
		
			
				|  |  |  |  |       add_transfer( | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.q, | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.position.q, | 
		
	
		
			
				|  |  |  |  |           context->hex.regions[data->selected_region]->region, | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, q), | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, position) + offsetof(HexCoord, q), | 
		
	
		
			
				|  |  |  |  |           sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |           context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |           &context->render); | 
		
	
	
		
			
				
					|  |  |  | @ -1063,11 +1128,11 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods) | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_J: | 
		
	
		
			
				|  |  |  |  |     if(context->hex.regions[data->selected_region] != NULL) { | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.r += 1; | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.position.r += 1; | 
		
	
		
			
				|  |  |  |  |       add_transfer( | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.r, | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.position.r, | 
		
	
		
			
				|  |  |  |  |           context->hex.regions[data->selected_region]->region, | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, r), | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, position) + offsetof(HexCoord, r), | 
		
	
		
			
				|  |  |  |  |           sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |           context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |           &context->render); | 
		
	
	
		
			
				
					|  |  |  | @ -1076,11 +1141,11 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods) | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_L: | 
		
	
		
			
				|  |  |  |  |     if(context->hex.regions[data->selected_region] != NULL) { | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.r -= 1; | 
		
	
		
			
				|  |  |  |  |       context->hex.regions[data->selected_region]->data.position.r -= 1; | 
		
	
		
			
				|  |  |  |  |       add_transfer( | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.r, | 
		
	
		
			
				|  |  |  |  |           &context->hex.regions[data->selected_region]->data.position.r, | 
		
	
		
			
				|  |  |  |  |           context->hex.regions[data->selected_region]->region, | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, r), | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, position) + offsetof(HexCoord, r), | 
		
	
		
			
				|  |  |  |  |           sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |           context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |           &context->render); | 
		
	
	
		
			
				
					|  |  |  | @ -1116,35 +1181,54 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_Y: | 
		
	
		
			
				|  |  |  |  |     region = context->hex.regions[context->hex.data.clicked_region]; | 
		
	
		
			
				|  |  |  |  |     if(region != NULL) { | 
		
	
		
			
				|  |  |  |  |       region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] += 0.1;  | 
		
	
		
			
				|  |  |  |  |       add_transfer( | 
		
	
		
			
				|  |  |  |  |           ®ion->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1], | 
		
	
		
			
				|  |  |  |  |           region->region, | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, hexes) | 
		
	
		
			
				|  |  |  |  |           + sizeof(GPUHex)*context->hex.data.clicked_hex | 
		
	
		
			
				|  |  |  |  |           + offsetof(GPUHex, height) | 
		
	
		
			
				|  |  |  |  |           + sizeof(float)*(context->hex.data.clicked_vertex-1), | 
		
	
		
			
				|  |  |  |  |           sizeof(float), | 
		
	
		
			
				|  |  |  |  |           context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |           &context->render); | 
		
	
		
			
				|  |  |  |  |     if(region != NULL && context->hex.data.clicked_vertex != 0) { | 
		
	
		
			
				|  |  |  |  |       float height = region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] + 0.1;  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       if(~mods & GLFW_MOD_CONTROL) { | 
		
	
		
			
				|  |  |  |  |         uint32_t n_vertex[2], n_hex[2]; | 
		
	
		
			
				|  |  |  |  |         HexCoord n_region[2]; | 
		
	
		
			
				|  |  |  |  |         HexCoord world, region_center; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         region_qr(region->data.position, ®ion_center); | 
		
	
		
			
				|  |  |  |  |         hex_qr(context->hex.data.clicked_hex, &world); | 
		
	
		
			
				|  |  |  |  |         hex_add(region_center, &world); | 
		
	
		
			
				|  |  |  |  |         hex_vertex_neighbors(context->hex.data.clicked_vertex, world, n_vertex, n_region, n_hex);   | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         uint32_t n0, n1; | 
		
	
		
			
				|  |  |  |  |         first_matching_region(n_region[0], region->data.y, &n0, &context->hex); | 
		
	
		
			
				|  |  |  |  |         first_matching_region(n_region[1], region->data.y, &n1, &context->hex); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if(n0 != MAX_LOADED_REGIONS) set_vertex_height(height, n0, n_hex[0], n_vertex[0], context); | 
		
	
		
			
				|  |  |  |  |         if(n1 != MAX_LOADED_REGIONS) set_vertex_height(height, n1, n_hex[1], n_vertex[1], context); | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |       set_vertex_height(height, context->hex.data.clicked_region, context->hex.data.clicked_hex, context->hex.data.clicked_vertex, context); | 
		
	
		
			
				|  |  |  |  |       update_hex_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_H: | 
		
	
		
			
				|  |  |  |  |     region = context->hex.regions[context->hex.data.clicked_region]; | 
		
	
		
			
				|  |  |  |  |     if(region != NULL) { | 
		
	
		
			
				|  |  |  |  |       region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] -= 0.1;  | 
		
	
		
			
				|  |  |  |  |       add_transfer( | 
		
	
		
			
				|  |  |  |  |           ®ion->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1], | 
		
	
		
			
				|  |  |  |  |           region->region, | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, hexes) | 
		
	
		
			
				|  |  |  |  |           + sizeof(GPUHex)*context->hex.data.clicked_hex | 
		
	
		
			
				|  |  |  |  |           + offsetof(GPUHex, height) | 
		
	
		
			
				|  |  |  |  |           + sizeof(float)*(context->hex.data.clicked_vertex-1), | 
		
	
		
			
				|  |  |  |  |           sizeof(float), | 
		
	
		
			
				|  |  |  |  |           context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |           &context->render); | 
		
	
		
			
				|  |  |  |  |     if(region != NULL && context->hex.data.clicked_vertex != 0) { | 
		
	
		
			
				|  |  |  |  |       float height = region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] - 0.1;  | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       if(~mods & GLFW_MOD_CONTROL) { | 
		
	
		
			
				|  |  |  |  |         uint32_t n_vertex[2], n_hex[2]; | 
		
	
		
			
				|  |  |  |  |         HexCoord n_region[2]; | 
		
	
		
			
				|  |  |  |  |         HexCoord world, region_center; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         region_qr(region->data.position, ®ion_center); | 
		
	
		
			
				|  |  |  |  |         hex_qr(context->hex.data.clicked_hex, &world); | 
		
	
		
			
				|  |  |  |  |         hex_add(region_center, &world); | 
		
	
		
			
				|  |  |  |  |         hex_vertex_neighbors(context->hex.data.clicked_vertex, world, n_vertex, n_region, n_hex);   | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         uint32_t n0, n1; | 
		
	
		
			
				|  |  |  |  |         first_matching_region(n_region[0], region->data.y, &n0, &context->hex); | 
		
	
		
			
				|  |  |  |  |         first_matching_region(n_region[1], region->data.y, &n1, &context->hex); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if(n0 != MAX_LOADED_REGIONS) set_vertex_height(height, n0, n_hex[0], n_vertex[0], context); | 
		
	
		
			
				|  |  |  |  |         if(n1 != MAX_LOADED_REGIONS) set_vertex_height(height, n1, n_hex[1], n_vertex[1], context); | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |       set_vertex_height(height, context->hex.data.clicked_region, context->hex.data.clicked_hex, context->hex.data.clicked_vertex, context); | 
		
	
		
			
				|  |  |  |  |       update_hex_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
	
		
			
				
					|  |  |  | @ -1152,17 +1236,24 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods) | 
		
	
		
			
				|  |  |  |  |   case GLFW_KEY_E: | 
		
	
		
			
				|  |  |  |  |     region = context->hex.regions[context->hex.data.clicked_region]; | 
		
	
		
			
				|  |  |  |  |     if(region != NULL) { | 
		
	
		
			
				|  |  |  |  |       region->data.hexes[context->hex.data.clicked_hex].color[context->hex.data.clicked_vertex] = hex_color(data->current);  | 
		
	
		
			
				|  |  |  |  |       add_transfer( | 
		
	
		
			
				|  |  |  |  |           ®ion->data.hexes[context->hex.data.clicked_hex].color[context->hex.data.clicked_vertex], | 
		
	
		
			
				|  |  |  |  |           region->region, | 
		
	
		
			
				|  |  |  |  |           offsetof(GPUHexRegion, hexes) | 
		
	
		
			
				|  |  |  |  |           + sizeof(GPUHex)*context->hex.data.clicked_hex | 
		
	
		
			
				|  |  |  |  |           + offsetof(GPUHex, color) | 
		
	
		
			
				|  |  |  |  |           + sizeof(uint32_t)*(context->hex.data.clicked_vertex), | 
		
	
		
			
				|  |  |  |  |           sizeof(uint32_t), | 
		
	
		
			
				|  |  |  |  |           context->render.current_frame, | 
		
	
		
			
				|  |  |  |  |           &context->render); | 
		
	
		
			
				|  |  |  |  |       uint32_t n_vertex[2], n_hex[2]; | 
		
	
		
			
				|  |  |  |  |       HexCoord n_region[2]; | 
		
	
		
			
				|  |  |  |  |       HexCoord world, region_center; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       if(context->hex.data.clicked_vertex != 0) { | 
		
	
		
			
				|  |  |  |  |         region_qr(region->data.position, ®ion_center); | 
		
	
		
			
				|  |  |  |  |         hex_qr(context->hex.data.clicked_hex, &world); | 
		
	
		
			
				|  |  |  |  |         hex_add(region_center, &world); | 
		
	
		
			
				|  |  |  |  |         hex_vertex_neighbors(context->hex.data.clicked_vertex, world, n_vertex, n_region, n_hex);   | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         uint32_t n0, n1; | 
		
	
		
			
				|  |  |  |  |         first_matching_region(n_region[0], region->data.y, &n0, &context->hex); | 
		
	
		
			
				|  |  |  |  |         first_matching_region(n_region[1], region->data.y, &n1, &context->hex); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         if(n0 != MAX_LOADED_REGIONS) set_vertex_color(data->current, n0, n_hex[0], n_vertex[0], context); | 
		
	
		
			
				|  |  |  |  |         if(n1 != MAX_LOADED_REGIONS) set_vertex_color(data->current, n1, n_hex[1], n_vertex[1], context); | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |       set_vertex_color(data->current, context->hex.data.clicked_region, context->hex.data.clicked_hex, context->hex.data.clicked_vertex, context); | 
		
	
		
			
				|  |  |  |  |       update_hex_info_ui(context); | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     break; | 
		
	
	
		
			
				
					|  |  |  | @ -1181,11 +1272,6 @@ void editor_frame(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |     data->last_clicked_vertex = context->hex.data.clicked_vertex; | 
		
	
		
			
				|  |  |  |  |     update_hex_info_ui(context); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(data->selected_region != data->last_selected_region) { | 
		
	
		
			
				|  |  |  |  |     data->last_selected_region = data->selected_region; | 
		
	
		
			
				|  |  |  |  |     update_region_info_ui(context); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void editor_startup(ClientContext* context) { | 
		
	
	
		
			
				
					|  |  |  | @ -1194,22 +1280,6 @@ void editor_startup(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   color_ui(context); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hex_vertex_neighbors( | 
		
	
		
			
				|  |  |  |  |     uint32_t vertex, HexCoord region, uint32_t hex, | 
		
	
		
			
				|  |  |  |  |     uint32_t n_vertex[2], HexCoord n_region[2], uint32_t n_hex[2]) { | 
		
	
		
			
				|  |  |  |  |   HexCoord n1 = hex_directions_qr[(vertex+1) % 6]; | 
		
	
		
			
				|  |  |  |  |   HexCoord n2 = hex_directions_qr[(vertex+2) % 6]; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   HexCoord hex_world; | 
		
	
		
			
				|  |  |  |  |   HexCoord region_world; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   region_qr(region, ®ion_world); | 
		
	
		
			
				|  |  |  |  |   hex_qr(hex, &hex_world); | 
		
	
		
			
				|  |  |  |  |   hex_add(region_world, &hex_world); | 
		
	
		
			
				|  |  |  |  |   hex_add(hex_world, &n1); | 
		
	
		
			
				|  |  |  |  |   hex_add(hex_world, &n2); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | int main() { | 
		
	
		
			
				|  |  |  |  |   EditorData* data = malloc(sizeof(EditorData)); | 
		
	
		
			
				|  |  |  |  |   memset(data, 0, sizeof(EditorData)); | 
		
	
	
		
			
				
					|  |  |  | 
 |