|  |  |  | @ -92,16 +92,26 @@ uint32_t add_hex_region(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | #define COLOR_PICK_CONTAINER_ID 0x03 | 
		
	
		
			
				|  |  |  |  | typedef struct ColorUIDataStruct { | 
		
	
		
			
				|  |  |  |  |   vec3 current; | 
		
	
		
			
				|  |  |  |  |   vec3 saved[12]; | 
		
	
		
			
				|  |  |  |  |   char string[8]; | 
		
	
		
			
				|  |  |  |  |   int string_len; | 
		
	
		
			
				|  |  |  |  | } ColorUIData; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | float floatmod(float a, float b) { | 
		
	
		
			
				|  |  |  |  |   return a - b*floor(a/b); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hsv_to_rgb(vec3 hsv, vec3 rgb) { | 
		
	
		
			
				|  |  |  |  |   float C = hsv[1] * hsv[2]; | 
		
	
		
			
				|  |  |  |  |   float H = hsv[0]*6; | 
		
	
		
			
				|  |  |  |  |   float X = C * (1 - fabs((H - 2 * floor( H / 2 )) - 1)); | 
		
	
		
			
				|  |  |  |  |   float X = C * (1 - fabs(floatmod(H, 2) - 1)); | 
		
	
		
			
				|  |  |  |  |   vec4 temp = {0, 0, 0, 0}; | 
		
	
		
			
				|  |  |  |  |   if(0 <= H && H <= 1) { | 
		
	
		
			
				|  |  |  |  |     temp[0] = C; | 
		
	
		
			
				|  |  |  |  |     temp[1] = X; | 
		
	
		
			
				|  |  |  |  |   } else if(1 <= H && H  <= 2) { | 
		
	
		
			
				|  |  |  |  |   } else if(1 <= H && H <= 2) { | 
		
	
		
			
				|  |  |  |  |     temp[0] = X; | 
		
	
		
			
				|  |  |  |  |     temp[1] = C; | 
		
	
		
			
				|  |  |  |  |   } else if(2 <= H && H <= 3) { | 
		
	
	
		
			
				
					|  |  |  | @ -124,24 +134,27 @@ void hsv_to_rgb(vec3 hsv, vec3 rgb) { | 
		
	
		
			
				|  |  |  |  |    rgb[2] = temp[2] + m; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void rgb_string_set(UIContext* ui, RenderContext* gpu, vec3 hsv) { | 
		
	
		
			
				|  |  |  |  | void rgb_string_set(UIContext* ui, RenderContext* gpu, ColorUIData* data, vec3 hsv) { | 
		
	
		
			
				|  |  |  |  |   vec3 rgb; | 
		
	
		
			
				|  |  |  |  |   hsv_to_rgb(hsv, rgb); | 
		
	
		
			
				|  |  |  |  |   char temp[10]; | 
		
	
		
			
				|  |  |  |  |   snprintf(temp, 10, "#%02x%02x%02x", | 
		
	
		
			
				|  |  |  |  |   snprintf(data->string, 8, "#%02X%02X%02X", | 
		
	
		
			
				|  |  |  |  |       (uint)(rgb[0]*255), | 
		
	
		
			
				|  |  |  |  |       (uint)(rgb[1]*255), | 
		
	
		
			
				|  |  |  |  |       (uint)(rgb[2]*255)); | 
		
	
		
			
				|  |  |  |  |   update_ui_string(temp, COLOR_PICK_CONTAINER_ID, 0, 0, ui, gpu); | 
		
	
		
			
				|  |  |  |  |   data->string_len = 6; | 
		
	
		
			
				|  |  |  |  |   update_ui_string(data->string, COLOR_PICK_CONTAINER_ID, 0, 0, ui, gpu); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void sv_square_pick(UIContext* ui, RenderContext* gpu, float s, float v) { | 
		
	
		
			
				|  |  |  |  | void sv_square_pick(UIContext* ui, RenderContext* gpu, ColorUIData* data, float s, float v) { | 
		
	
		
			
				|  |  |  |  |   if(s < 0) s = 0; | 
		
	
		
			
				|  |  |  |  |   if(s > 1) s = 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(v < 0) v = 0; | 
		
	
		
			
				|  |  |  |  |   if(v > 1) v = 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   data->current[1] = s; | 
		
	
		
			
				|  |  |  |  |   data->current[2] = 1-v; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Container* container = context_container(COLOR_PICK_CONTAINER_ID, ui); | 
		
	
		
			
				|  |  |  |  |   Layer* layer = &container->layers[0]; | 
		
	
		
			
				|  |  |  |  |   GPUDrawable* select_outline = &layer->drawables_buffer[3]; | 
		
	
	
		
			
				
					|  |  |  | @ -186,47 +199,52 @@ void sv_square_pick(UIContext* ui, RenderContext* gpu, float s, float v) { | 
		
	
		
			
				|  |  |  |  |       4*sizeof(vec4), | 
		
	
		
			
				|  |  |  |  |       gpu); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   rgb_string_set(ui, gpu, select->color[0]); | 
		
	
		
			
				|  |  |  |  |   rgb_string_set(ui, gpu, data, select->color[0]); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void sv_square_button_callback(UIContext* ui, RenderContext* gpu, float x, float y, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  | void sv_square_button_callback(void* data, UIContext* ui, RenderContext* gpu, float x, float y, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |   (void)mods; | 
		
	
		
			
				|  |  |  |  |   (void)x; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(action == GLFW_PRESS && button == GLFW_MOUSE_BUTTON_LEFT) { | 
		
	
		
			
				|  |  |  |  |     set_active_element(COLOR_PICK_CONTAINER_ID, 0, 1, ui); | 
		
	
		
			
				|  |  |  |  |     sv_square_pick(ui, gpu, x, y); | 
		
	
		
			
				|  |  |  |  |     sv_square_pick(ui, gpu, data, x, y); | 
		
	
		
			
				|  |  |  |  |   } else if(action == GLFW_RELEASE && button == GLFW_MOUSE_BUTTON_LEFT) { | 
		
	
		
			
				|  |  |  |  |     clear_active_element(ui, gpu); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void sv_square_cursor_callback(UIContext* ui, RenderContext* gpu, float x, float y) { | 
		
	
		
			
				|  |  |  |  | void sv_square_cursor_callback(void* data, UIContext* ui, RenderContext* gpu, float x, float y) { | 
		
	
		
			
				|  |  |  |  |   if(ui->active_element == 1 | 
		
	
		
			
				|  |  |  |  |   && ui->active_layer == 0 | 
		
	
		
			
				|  |  |  |  |   && ui->active_container == COLOR_PICK_CONTAINER_ID) { | 
		
	
		
			
				|  |  |  |  |     sv_square_pick(ui, gpu, x, y); | 
		
	
		
			
				|  |  |  |  |     sv_square_pick(ui, gpu, data, x, y); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hue_bar_set(UIContext* ui, RenderContext* gpu, float y) { | 
		
	
		
			
				|  |  |  |  | void hue_bar_set(UIContext* ui, RenderContext* gpu, ColorUIData* data, float y) { | 
		
	
		
			
				|  |  |  |  |   if(y < 0) y = 0; | 
		
	
		
			
				|  |  |  |  |   if(y > 1) y = 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   data->current[0] = y; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Container* container = context_container(COLOR_PICK_CONTAINER_ID, ui); | 
		
	
		
			
				|  |  |  |  |   Layer* layer = &container->layers[0]; | 
		
	
		
			
				|  |  |  |  |   GPUDrawable* sv_square = &layer->drawables_buffer[1]; | 
		
	
		
			
				|  |  |  |  |   GPUDrawable* select = &layer->drawables_buffer[4]; | 
		
	
		
			
				|  |  |  |  |   GPUDrawable* sv_select = &layer->drawables_buffer[4]; | 
		
	
		
			
				|  |  |  |  |   GPUDrawable* hue_select = &layer->drawables_buffer[6]; | 
		
	
		
			
				|  |  |  |  |    | 
		
	
		
			
				|  |  |  |  |   sv_square->color[0][0] = y; | 
		
	
		
			
				|  |  |  |  |   sv_square->color[1][0] = y; | 
		
	
		
			
				|  |  |  |  |   sv_square->color[2][0] = y; | 
		
	
		
			
				|  |  |  |  |   sv_square->color[3][0] = y; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   select->color[0][0] = y; | 
		
	
		
			
				|  |  |  |  |   select->color[1][0] = y; | 
		
	
		
			
				|  |  |  |  |   select->color[2][0] = y; | 
		
	
		
			
				|  |  |  |  |   select->color[3][0] = y; | 
		
	
		
			
				|  |  |  |  |   sv_select->color[0][0] = y; | 
		
	
		
			
				|  |  |  |  |   sv_select->color[1][0] = y; | 
		
	
		
			
				|  |  |  |  |   sv_select->color[2][0] = y; | 
		
	
		
			
				|  |  |  |  |   sv_select->color[3][0] = y; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   hue_select->pos[1] = 2 + y*130; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   add_transfers( | 
		
	
		
			
				|  |  |  |  |       &sv_square->color[0], | 
		
	
	
		
			
				
					|  |  |  | @ -236,39 +254,46 @@ void hue_bar_set(UIContext* ui, RenderContext* gpu, float y) { | 
		
	
		
			
				|  |  |  |  |       gpu); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   add_transfers( | 
		
	
		
			
				|  |  |  |  |       &select->color[0], | 
		
	
		
			
				|  |  |  |  |       &sv_select->color[0], | 
		
	
		
			
				|  |  |  |  |       layer->drawables, | 
		
	
		
			
				|  |  |  |  |       4*sizeof(GPUDrawable) + offsetof(GPUDrawable, color), | 
		
	
		
			
				|  |  |  |  |       4*sizeof(vec4), | 
		
	
		
			
				|  |  |  |  |       gpu); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   rgb_string_set(ui, gpu, select->color[0]); | 
		
	
		
			
				|  |  |  |  |   add_transfers( | 
		
	
		
			
				|  |  |  |  |       &hue_select->pos[1], | 
		
	
		
			
				|  |  |  |  |       layer->drawables, | 
		
	
		
			
				|  |  |  |  |       6*sizeof(GPUDrawable) + offsetof(GPUDrawable, pos) + sizeof(float), | 
		
	
		
			
				|  |  |  |  |       1*sizeof(float), | 
		
	
		
			
				|  |  |  |  |       gpu); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   rgb_string_set(ui, gpu, data, sv_select->color[0]); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hue_bar_scroll_callback(UIContext* ui, RenderContext* gpu, double x, double y) { | 
		
	
		
			
				|  |  |  |  | void hue_bar_scroll_callback(void* data, UIContext* ui, RenderContext* gpu, double x, double y) { | 
		
	
		
			
				|  |  |  |  |   (void)x; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   Container* container = context_container(COLOR_PICK_CONTAINER_ID, ui); | 
		
	
		
			
				|  |  |  |  |   hue_bar_set(ui, gpu, y*0.01 + container->layers[0].drawables_buffer[1].color[0][0]); | 
		
	
		
			
				|  |  |  |  |   hue_bar_set(ui, gpu, data, y*0.01 + container->layers[0].drawables_buffer[1].color[0][0]); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hue_bar_cursor_callback(UIContext* ui, RenderContext* gpu, float x, float y) { | 
		
	
		
			
				|  |  |  |  | void hue_bar_cursor_callback(void*data, UIContext* ui, RenderContext* gpu, float x, float y) { | 
		
	
		
			
				|  |  |  |  |   (void)x; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(ui->active_element == 2 | 
		
	
		
			
				|  |  |  |  |   && ui->active_layer == 0 | 
		
	
		
			
				|  |  |  |  |   && ui->active_container == COLOR_PICK_CONTAINER_ID) { | 
		
	
		
			
				|  |  |  |  |     hue_bar_set(ui, gpu, y); | 
		
	
		
			
				|  |  |  |  |     hue_bar_set(ui, gpu, data, y); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hue_bar_button_callback(UIContext* ui, RenderContext* gpu, float x, float y, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  | void hue_bar_button_callback(void* data, UIContext* ui, RenderContext* gpu, float x, float y, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |   (void)mods; | 
		
	
		
			
				|  |  |  |  |   (void)x; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(action == GLFW_PRESS && button == GLFW_MOUSE_BUTTON_LEFT) { | 
		
	
		
			
				|  |  |  |  |     set_active_element(COLOR_PICK_CONTAINER_ID, 0, 2, ui); | 
		
	
		
			
				|  |  |  |  |     hue_bar_set(ui, gpu, y); | 
		
	
		
			
				|  |  |  |  |     hue_bar_set(ui, gpu, data, y); | 
		
	
		
			
				|  |  |  |  |   } else if(action == GLFW_RELEASE && button == GLFW_MOUSE_BUTTON_LEFT) { | 
		
	
		
			
				|  |  |  |  |     clear_active_element(ui, gpu); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
	
		
			
				
					|  |  |  | @ -296,18 +321,107 @@ void hex_string_set_color(UIContext* ui, RenderContext* gpu, float color) { | 
		
	
		
			
				|  |  |  |  |       gpu); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | bool hex_string_key_callback(UIContext* ui, RenderContext* gpu, int key, int action, int mods) { | 
		
	
		
			
				|  |  |  |  | void hex_string_text_callback(void* ptr, UIContext* ui, RenderContext* gpu, unsigned int codepoint) { | 
		
	
		
			
				|  |  |  |  |   ColorUIData* data = ptr; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(codepoint >= 'a' && codepoint <= 'f') { | 
		
	
		
			
				|  |  |  |  |     codepoint += 'A' - 'a'; | 
		
	
		
			
				|  |  |  |  |   } else if(!((codepoint >= 'A' && codepoint <= 'F') || (codepoint >= '0' && codepoint <= '9'))) { | 
		
	
		
			
				|  |  |  |  |     return; | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(data->string_len < 6) { | 
		
	
		
			
				|  |  |  |  |     data->string_len += 1; | 
		
	
		
			
				|  |  |  |  |     data->string[data->string_len] = codepoint; | 
		
	
		
			
				|  |  |  |  |     update_ui_string(data->string, COLOR_PICK_CONTAINER_ID, 0, 0, ui, gpu); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void rgb_to_hsv(vec3 rgb, vec3 hsv) { | 
		
	
		
			
				|  |  |  |  |   hsv[2] = max(rgb[0], max(rgb[1], rgb[2])); | 
		
	
		
			
				|  |  |  |  |   float M = min(rgb[0], min(rgb[1], rgb[2])); | 
		
	
		
			
				|  |  |  |  |   float C = hsv[2] - M; | 
		
	
		
			
				|  |  |  |  |   hsv[1] = C / hsv[2]; | 
		
	
		
			
				|  |  |  |  |   float X; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(hsv[2] == rgb[0] && M == rgb[2]) { | 
		
	
		
			
				|  |  |  |  |     X = rgb[1] - M; | 
		
	
		
			
				|  |  |  |  |     hsv[0] = (X/C + 0)/6; | 
		
	
		
			
				|  |  |  |  |     // H = [0, 1]
 | 
		
	
		
			
				|  |  |  |  |   } else if(hsv[2] == rgb[1] && M == rgb[2]) { | 
		
	
		
			
				|  |  |  |  |     X = 1 - rgb[0] - M; | 
		
	
		
			
				|  |  |  |  |     hsv[0] = (X/C + 1)/6; | 
		
	
		
			
				|  |  |  |  |     // H = [1, 2]
 | 
		
	
		
			
				|  |  |  |  |   } else if(hsv[2] == rgb[1] && M == rgb[0]) { | 
		
	
		
			
				|  |  |  |  |     X = rgb[2] - M; | 
		
	
		
			
				|  |  |  |  |     hsv[0] = (X/C + 2)/6; | 
		
	
		
			
				|  |  |  |  |     // H = [2, 3]
 | 
		
	
		
			
				|  |  |  |  |   } else if(hsv[2] == rgb[2] && M == rgb[0]) { | 
		
	
		
			
				|  |  |  |  |     X = 1 - rgb[1] - M; | 
		
	
		
			
				|  |  |  |  |     hsv[0] = (X/C + 3)/6; | 
		
	
		
			
				|  |  |  |  |     // H = [3, 4]
 | 
		
	
		
			
				|  |  |  |  |   } else if(hsv[2] == rgb[2] && M == rgb[1]) { | 
		
	
		
			
				|  |  |  |  |     X = rgb[0] - M; | 
		
	
		
			
				|  |  |  |  |     hsv[0] = (X/C + 4)/6; | 
		
	
		
			
				|  |  |  |  |     // H = [4, 5]
 | 
		
	
		
			
				|  |  |  |  |   } else if(hsv[2] == rgb[0] && M == rgb[1]) { | 
		
	
		
			
				|  |  |  |  |     X = 1 - rgb[2] - M; | 
		
	
		
			
				|  |  |  |  |     hsv[0] = (X/C + 5)/6; | 
		
	
		
			
				|  |  |  |  |     // H = [5, 6]
 | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | bool hex_string_key_callback(void* ptr, UIContext* ui, RenderContext* gpu, int key, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |   (void)mods; | 
		
	
		
			
				|  |  |  |  |   ColorUIData* data = ptr; | 
		
	
		
			
				|  |  |  |  |   char tmp[3]; | 
		
	
		
			
				|  |  |  |  |   vec3 rgb; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   if(action == GLFW_PRESS && key == GLFW_KEY_ESCAPE) { | 
		
	
		
			
				|  |  |  |  |     clear_active_element(ui, gpu); | 
		
	
		
			
				|  |  |  |  |     return true; | 
		
	
		
			
				|  |  |  |  |   if(action == GLFW_PRESS) { | 
		
	
		
			
				|  |  |  |  |     switch(key) { | 
		
	
		
			
				|  |  |  |  |     case GLFW_KEY_ESCAPE: | 
		
	
		
			
				|  |  |  |  |       rgb_string_set(ui, gpu, data, data->current); | 
		
	
		
			
				|  |  |  |  |       clear_active_element(ui, gpu); | 
		
	
		
			
				|  |  |  |  |       break; | 
		
	
		
			
				|  |  |  |  |     case GLFW_KEY_ENTER: | 
		
	
		
			
				|  |  |  |  |       // TODO: validate hex string and reset or set hsv
 | 
		
	
		
			
				|  |  |  |  |       tmp[0] = data->string[1]; | 
		
	
		
			
				|  |  |  |  |       tmp[1] = data->string[2]; | 
		
	
		
			
				|  |  |  |  |       tmp[2] = 0; | 
		
	
		
			
				|  |  |  |  |       rgb[0] = strtol(tmp, NULL, 16)/255.0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       tmp[0] = data->string[3]; | 
		
	
		
			
				|  |  |  |  |       tmp[1] = data->string[4]; | 
		
	
		
			
				|  |  |  |  |       tmp[2] = 0; | 
		
	
		
			
				|  |  |  |  |       rgb[1] = strtol(tmp, NULL, 16)/255.0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       tmp[0] = data->string[5]; | 
		
	
		
			
				|  |  |  |  |       tmp[1] = data->string[6]; | 
		
	
		
			
				|  |  |  |  |       tmp[2] = 0; | 
		
	
		
			
				|  |  |  |  |       rgb[2] = strtol(tmp, NULL, 16)/255.0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       rgb_to_hsv(rgb, data->current); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       hue_bar_set(ui, gpu, data, data->current[0]); | 
		
	
		
			
				|  |  |  |  |       sv_square_pick(ui, gpu, data, data->current[1], 1-data->current[2]); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       clear_active_element(ui, gpu); | 
		
	
		
			
				|  |  |  |  |       break; | 
		
	
		
			
				|  |  |  |  |     case GLFW_KEY_BACKSPACE: | 
		
	
		
			
				|  |  |  |  |       if(data->string_len > 0) { | 
		
	
		
			
				|  |  |  |  |         data->string[data->string_len] = '\0'; | 
		
	
		
			
				|  |  |  |  |         data->string_len -= 1; | 
		
	
		
			
				|  |  |  |  |         update_ui_string(data->string, COLOR_PICK_CONTAINER_ID, 0, 0, ui, gpu); | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  |       break; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return false; | 
		
	
		
			
				|  |  |  |  |   return true; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hex_string_button_callback(UIContext* ui, RenderContext* gpu, float x, float y, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  | void hex_string_button_callback(void* data, UIContext* ui, RenderContext* gpu, float x, float y, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |   (void)data; | 
		
	
		
			
				|  |  |  |  |   (void)mods; | 
		
	
		
			
				|  |  |  |  |   (void)x; | 
		
	
		
			
				|  |  |  |  |   (void)y; | 
		
	
	
		
			
				
					|  |  |  | @ -318,7 +432,7 @@ void hex_string_button_callback(UIContext* ui, RenderContext* gpu, float x, floa | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void hex_string_deselect_callback(UIContext* ui, RenderContext* gpu) { | 
		
	
		
			
				|  |  |  |  | void hex_string_deselect_callback(void* data, UIContext* ui, RenderContext* gpu) { | 
		
	
		
			
				|  |  |  |  |   hex_string_set_color(ui, gpu, 0); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -329,7 +443,7 @@ VkResult color_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |       .color = {1, 1, 1, 1}, | 
		
	
		
			
				|  |  |  |  |       .size = 16, | 
		
	
		
			
				|  |  |  |  |       .offset = 0, | 
		
	
		
			
				|  |  |  |  |       .length = 9, | 
		
	
		
			
				|  |  |  |  |       .length = 7, | 
		
	
		
			
				|  |  |  |  |       .font = 0, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
	
		
			
				
					|  |  |  | @ -355,13 +469,13 @@ VkResult color_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |       .events = UI_EVENT_BUTTON | UI_EVENT_SCROLL, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .pos = {9, 9}, | 
		
	
		
			
				|  |  |  |  |       .pos = {130-4, 130-4}, | 
		
	
		
			
				|  |  |  |  |       .size = {7, 7}, | 
		
	
		
			
				|  |  |  |  |       .color = {{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}}, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .type = DRAWABLE_TYPE_RECT_HSV, | 
		
	
		
			
				|  |  |  |  |       .pos = {10, 10}, | 
		
	
		
			
				|  |  |  |  |       .pos = {130-3, 130-3}, | 
		
	
		
			
				|  |  |  |  |       .size = {5, 5}, | 
		
	
		
			
				|  |  |  |  |       .color = {{1, 0, 0, 1}, {1, 0, 0, 1}, {1, 0, 0, 1}, {1, 0, 0, 1}}, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
	
		
			
				
					|  |  |  | @ -370,6 +484,11 @@ VkResult color_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |       .size = {95, 15}, | 
		
	
		
			
				|  |  |  |  |       .events = UI_EVENT_BUTTON | UI_EVENT_CURSOR, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .pos = {134, 2}, | 
		
	
		
			
				|  |  |  |  |       .size = {10, 1}, | 
		
	
		
			
				|  |  |  |  |       .color = {{0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}, {0, 0, 0, 1}}, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .pos = {146, 2}, | 
		
	
		
			
				|  |  |  |  |       .size = {20, 20}, | 
		
	
	
		
			
				
					|  |  |  | @ -445,16 +564,32 @@ VkResult color_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |     .num_drawables = sizeof(drawables)/sizeof(GPUDrawable), | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ColorUIData* data = malloc(sizeof(ColorUIData)); | 
		
	
		
			
				|  |  |  |  |   data->string_len = 6; | 
		
	
		
			
				|  |  |  |  |   data->string[0] = '#'; | 
		
	
		
			
				|  |  |  |  |   data->string[1] = '0'; | 
		
	
		
			
				|  |  |  |  |   data->string[2] = '0'; | 
		
	
		
			
				|  |  |  |  |   data->string[3] = '0'; | 
		
	
		
			
				|  |  |  |  |   data->string[4] = '0'; | 
		
	
		
			
				|  |  |  |  |   data->string[5] = '0'; | 
		
	
		
			
				|  |  |  |  |   data->string[6] = '0'; | 
		
	
		
			
				|  |  |  |  |   data->string[7] = '\0'; | 
		
	
		
			
				|  |  |  |  |   data->current[0] = 0; | 
		
	
		
			
				|  |  |  |  |   data->current[1] = 0; | 
		
	
		
			
				|  |  |  |  |   data->current[2] = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   UICallbacks callbacks[] = { | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .layer = 0, | 
		
	
		
			
				|  |  |  |  |       .element = 1, | 
		
	
		
			
				|  |  |  |  |       .data = data, | 
		
	
		
			
				|  |  |  |  |       .button = sv_square_button_callback, | 
		
	
		
			
				|  |  |  |  |       .cursor = sv_square_cursor_callback, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .layer = 0, | 
		
	
		
			
				|  |  |  |  |       .element = 2, | 
		
	
		
			
				|  |  |  |  |       .data = data, | 
		
	
		
			
				|  |  |  |  |       .button = hue_bar_button_callback, | 
		
	
		
			
				|  |  |  |  |       .cursor = hue_bar_cursor_callback, | 
		
	
		
			
				|  |  |  |  |       .scroll = hue_bar_scroll_callback, | 
		
	
	
		
			
				
					|  |  |  | @ -462,8 +597,10 @@ VkResult color_ui(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |     { | 
		
	
		
			
				|  |  |  |  |       .layer = 0, | 
		
	
		
			
				|  |  |  |  |       .element = 5, | 
		
	
		
			
				|  |  |  |  |       .data = data, | 
		
	
		
			
				|  |  |  |  |       .button = hex_string_button_callback, | 
		
	
		
			
				|  |  |  |  |       .key = hex_string_key_callback, | 
		
	
		
			
				|  |  |  |  |       .text = hex_string_text_callback, | 
		
	
		
			
				|  |  |  |  |       .deselect = hex_string_deselect_callback, | 
		
	
		
			
				|  |  |  |  |     }, | 
		
	
		
			
				|  |  |  |  |   }; | 
		
	
	
		
			
				
					|  |  |  | @ -931,13 +1068,30 @@ VkResult main_thread(ClientContext* context) { | 
		
	
		
			
				|  |  |  |  |   return 0; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void text_callback(GLFWwindow* window, unsigned int codepoint) { | 
		
	
		
			
				|  |  |  |  |   ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); | 
		
	
		
			
				|  |  |  |  |   if(context->ui->active_callbacks != NULL && context->ui->active_callbacks->text != NULL) { | 
		
	
		
			
				|  |  |  |  |     context->ui->active_callbacks->text( | 
		
	
		
			
				|  |  |  |  |         context->ui->active_callbacks->data, | 
		
	
		
			
				|  |  |  |  |         context->ui, | 
		
	
		
			
				|  |  |  |  |         context->render, | 
		
	
		
			
				|  |  |  |  |         codepoint); | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |   (void)scancode; | 
		
	
		
			
				|  |  |  |  |   (void)mods; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); | 
		
	
		
			
				|  |  |  |  |   if(context->ui->active_callbacks != NULL && context->ui->active_callbacks->key != NULL) { | 
		
	
		
			
				|  |  |  |  |     if(context->ui->active_callbacks->key(context->ui, context->render, key, action, mods)) { | 
		
	
		
			
				|  |  |  |  |     if(context->ui->active_callbacks->key( | 
		
	
		
			
				|  |  |  |  |           context->ui->active_callbacks->data, | 
		
	
		
			
				|  |  |  |  |           context->ui, | 
		
	
		
			
				|  |  |  |  |           context->render, | 
		
	
		
			
				|  |  |  |  |           key, | 
		
	
		
			
				|  |  |  |  |           action, | 
		
	
		
			
				|  |  |  |  |           mods)) { | 
		
	
		
			
				|  |  |  |  |       return; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
	
		
			
				
					|  |  |  | @ -1202,8 +1356,9 @@ void button_callback(GLFWwindow* window, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |       (cursor[1] - element_pos[1])/element_size[1], | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  |      | 
		
	
		
			
				|  |  |  |  |     if(point[0] <= 1 && point[0] >= 0 && point[1] <= 1 && point[1] >= 0) { | 
		
	
		
			
				|  |  |  |  |     if((point[0] <= 1 && point[0] >= 0 && point[1] <= 1 && point[1] >= 0) || action == GLFW_RELEASE) { | 
		
	
		
			
				|  |  |  |  |       context->ui->active_callbacks->button( | 
		
	
		
			
				|  |  |  |  |           context->ui->active_callbacks->data, | 
		
	
		
			
				|  |  |  |  |           context->ui, | 
		
	
		
			
				|  |  |  |  |           context->render, | 
		
	
		
			
				|  |  |  |  |           point[0], | 
		
	
	
		
			
				
					|  |  |  | @ -1222,7 +1377,15 @@ void button_callback(GLFWwindow* window, int button, int action, int mods) { | 
		
	
		
			
				|  |  |  |  |     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->ui, context->render, position[0], position[1], button, action, mods); | 
		
	
		
			
				|  |  |  |  |           container_ptr->callbacks[c].button( | 
		
	
		
			
				|  |  |  |  |               container_ptr->callbacks[c].data, | 
		
	
		
			
				|  |  |  |  |               context->ui, | 
		
	
		
			
				|  |  |  |  |               context->render, | 
		
	
		
			
				|  |  |  |  |               position[0], | 
		
	
		
			
				|  |  |  |  |               position[1], | 
		
	
		
			
				|  |  |  |  |               button, | 
		
	
		
			
				|  |  |  |  |               action, | 
		
	
		
			
				|  |  |  |  |               mods); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
	
		
			
				
					|  |  |  | @ -1251,7 +1414,12 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); | 
		
	
		
			
				|  |  |  |  |   if(context->ui->active_callbacks != NULL && context->ui->active_callbacks->scroll != NULL) { | 
		
	
		
			
				|  |  |  |  |     context->ui->active_callbacks->scroll(context->ui, context->render, xoffset, yoffset); | 
		
	
		
			
				|  |  |  |  |     context->ui->active_callbacks->scroll( | 
		
	
		
			
				|  |  |  |  |         context->ui->active_callbacks->data, | 
		
	
		
			
				|  |  |  |  |         context->ui, | 
		
	
		
			
				|  |  |  |  |         context->render, | 
		
	
		
			
				|  |  |  |  |         xoffset, | 
		
	
		
			
				|  |  |  |  |         yoffset); | 
		
	
		
			
				|  |  |  |  |   } else if(ui_intersect( | 
		
	
		
			
				|  |  |  |  |         context->ui->cursor, | 
		
	
		
			
				|  |  |  |  |         context->render, | 
		
	
	
		
			
				
					|  |  |  | @ -1265,7 +1433,12 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { | 
		
	
		
			
				|  |  |  |  |     for(uint32_t c = 0; c < container_ptr->callback_count; c++) { | 
		
	
		
			
				|  |  |  |  |       if(container_ptr->callbacks[c].element == element) { | 
		
	
		
			
				|  |  |  |  |         if(container_ptr->callbacks[c].scroll != NULL) { | 
		
	
		
			
				|  |  |  |  |           container_ptr->callbacks[c].scroll(context->ui, context->render, xoffset, yoffset); | 
		
	
		
			
				|  |  |  |  |           container_ptr->callbacks[c].scroll( | 
		
	
		
			
				|  |  |  |  |               container_ptr->callbacks[c].data, | 
		
	
		
			
				|  |  |  |  |               context->ui, | 
		
	
		
			
				|  |  |  |  |               context->render, | 
		
	
		
			
				|  |  |  |  |               xoffset, | 
		
	
		
			
				|  |  |  |  |               yoffset); | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         break; | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
	
		
			
				
					|  |  |  | @ -1306,6 +1479,7 @@ void cursor_callback(GLFWwindow* window, double xpos, double ypos) { | 
		
	
		
			
				|  |  |  |  |         drawable_ptr->size[1], | 
		
	
		
			
				|  |  |  |  |       }; | 
		
	
		
			
				|  |  |  |  |       context->ui->active_callbacks->cursor( | 
		
	
		
			
				|  |  |  |  |           context->ui->active_callbacks->data, | 
		
	
		
			
				|  |  |  |  |           context->ui, | 
		
	
		
			
				|  |  |  |  |           context->render, | 
		
	
		
			
				|  |  |  |  |           (context->ui->cursor[0] - element_pos[0])/element_size[0], | 
		
	
	
		
			
				
					|  |  |  | @ -1315,7 +1489,12 @@ void cursor_callback(GLFWwindow* window, double xpos, double ypos) { | 
		
	
		
			
				|  |  |  |  |       for(uint32_t c = 0; c < container_ptr->callback_count; c++) { | 
		
	
		
			
				|  |  |  |  |         if(container_ptr->callbacks[c].element == element) { | 
		
	
		
			
				|  |  |  |  |           if(container_ptr->callbacks[c].cursor != NULL) { | 
		
	
		
			
				|  |  |  |  |             container_ptr->callbacks[c].cursor(context->ui, context->render, position[0], position[1]); | 
		
	
		
			
				|  |  |  |  |             container_ptr->callbacks[c].cursor( | 
		
	
		
			
				|  |  |  |  |                 container_ptr->callbacks[c].data, | 
		
	
		
			
				|  |  |  |  |                 context->ui, | 
		
	
		
			
				|  |  |  |  |                 context->render, | 
		
	
		
			
				|  |  |  |  |                 position[0], | 
		
	
		
			
				|  |  |  |  |                 position[1]); | 
		
	
		
			
				|  |  |  |  |           } | 
		
	
		
			
				|  |  |  |  |           break; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -1361,6 +1540,7 @@ int main() { | 
		
	
		
			
				|  |  |  |  |   glfwSetMouseButtonCallback(context.window, button_callback); | 
		
	
		
			
				|  |  |  |  |   glfwSetScrollCallback(context.window, scroll_callback); | 
		
	
		
			
				|  |  |  |  |   glfwSetCursorPosCallback(context.window, cursor_callback); | 
		
	
		
			
				|  |  |  |  |   glfwSetCharCallback(context.window, text_callback); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   int error; | 
		
	
		
			
				|  |  |  |  |   VkResult result; | 
		
	
	
		
			
				
					|  |  |  | 
 |