intermediate representation HSV
authorhgn <hgodden00@gmail.com>
Wed, 31 Jan 2024 05:25:58 +0000 (05:25 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 31 Jan 2024 05:25:58 +0000 (05:25 +0000)
vg_imgui.h
vg_m.h

index 32fab4928b9266885ba860e2e4fe2d70bafe360a..5c957ed2ba1b053b3002e4e64299b8a7d8b7c2d4 100644 (file)
@@ -1416,7 +1416,7 @@ static void ui_enum_post(void){
  * -----------------------------------------------------------------------------
  */
 
-static void _ui_slider( ui_rect box, 
+static enum ui_button_state _ui_slider( ui_rect box, 
                         f32 min, f32 max, f32 *value, const char *format ){
    f32 t;
 
@@ -1446,6 +1446,8 @@ static void _ui_slider( ui_rect box,
    char buf[32];
    snprintf( buf, sizeof(buf), format? format: "%.2f", *value );
    ui_text( box, buf, 1, k_ui_align_middle_center, 0 );
+
+   return state;
 }
 
 static void ui_slider( ui_rect inout_panel, const char *str_label, 
@@ -1472,8 +1474,13 @@ static void ui_colourpicker( ui_rect inout_panel, const char *str_label,
    ui_split_ratio( sliders[0], k_ui_axis_h, 0.5f, 2, sliders[0], sliders[1] );
    ui_split_ratio( sliders[2], k_ui_axis_h, 0.5f, 2, sliders[2], sliders[3] );
 
+   v4f hsv;
+   vg_rgb_hsv( value, hsv );
+
+   enum ui_button_state modified = 0x00;
+
    for( u32 i=0; i<4; i ++ ){
-      _ui_slider( sliders[i], 0.0f, 1.0f, value+i, 
+      modified |= _ui_slider( sliders[i], 0.0f, 1.0f, hsv+i, 
                      (const char *[]){ "hue %.2f",
                                        "sat %.2f",
                                        "lum %.2f",
@@ -1484,6 +1491,7 @@ static void ui_colourpicker( ui_rect inout_panel, const char *str_label,
    ui_split_ratio( left, k_ui_axis_v, 0.8f, 8, square, preview );
 
    u32 state = ui_colourbutton( square, 0, 0, 0, 0 );
+   modified |= state;
 
    enum ui_button_state 
       mask_using = 
@@ -1493,50 +1501,40 @@ static void ui_colourpicker( ui_rect inout_panel, const char *str_label,
    
    if( state & mask_using ){
       for( u32 i=0; i<2; i ++ ){
-         value[1+i] = vg_clampf( 
+         hsv[1+i] = vg_clampf( 
                         (f32)(vg_ui.mouse[i] - square[i]) / (f32)(square[2+i]),
                         0.0f, 1.0f );
       }
 
-      value[2] = 1.0f-value[2];
+      hsv[2] = 1.0f-hsv[2];
+   }
+
+   if( modified & (k_ui_button_click|k_ui_button_holding_inside|
+                   k_ui_button_holding_outside) ){
+      vg_hsv_rgb( hsv, value );
    }
 
    ui_outline( square, 1, ui_colour( state? k_ui_fg+3: k_ui_bg+3 ), 0 );
 
    /* preview colour */
-   i32 i = floorf( value[0]*6.0f );
-   f32 v = value[2],
-       f = value[0] * 6.0f - (f32)i,
-       p = v * (1.0f-value[1]),
-       q = v * (1.0f-f*value[1]),
-       t = v * (1.0f-(1.0f-f)*value[1]);
-
    v4f colour;
-
-   switch( i % 6 ){
-      case 0: colour[0] = v; colour[1] = t; colour[2] = p; break;
-      case 1: colour[0] = q; colour[1] = v; colour[2] = p; break;
-      case 2: colour[0] = p; colour[1] = v; colour[2] = t; break;
-      case 3: colour[0] = p; colour[1] = q; colour[2] = v; break;
-      case 4: colour[0] = t; colour[1] = p; colour[2] = v; break;
-      case 5: colour[0] = v; colour[1] = p; colour[2] = q; break;
-   }
+   vg_hsv_rgb( hsv, colour );
    colour[3] = 1.0f;
    ui_fill( preview, v4f_u32_colour( colour ) );
 
    /* Draw hsv shader thingy */
    ui_flush( k_ui_shader_colour, vg.window_x, vg.window_y );
    ui_fill_rect( square, 0xffffffff, (ui_px[4]){ 0,256,256,0 } );
-   vg_ui.hue = value[0];
+   vg_ui.hue = hsv[0];
    ui_flush( k_ui_shader_hsv, vg.window_x, vg.window_y );
 
-   ui_rect marker = { square[0] + value[1] * (f32)square[2] - 4, 
-                      square[1] + (1.0f-value[2]) * (f32)square[3] - 4,
+   ui_rect marker = { square[0] + hsv[1] * (f32)square[2] - 4, 
+                      square[1] + (1.0f-hsv[2]) * (f32)square[3] - 4,
                       8, 8 },
            lx     = { square[0],
-                      square[1] + (1.0f-value[2]) * (f32)square[3],
+                      square[1] + (1.0f-hsv[2]) * (f32)square[3],
                       square[2], 1 },
-           ly     = { square[0] + value[1] * (f32)square[2],
+           ly     = { square[0] + hsv[1] * (f32)square[2],
                       square[1],
                       1, square[3] };
 
diff --git a/vg_m.h b/vg_m.h
index 6cbac62295773393f84749c5b62b9b871efd2c4c..436ca63bbd5bf553cc9e39118b7e26cbcad7a1de 100644 (file)
--- a/vg_m.h
+++ b/vg_m.h
@@ -2531,4 +2531,54 @@ static void vg_rand_cone( vg_rand *rand, v3f out_dir, f32 angle ){
    out_dir[2] = cosf(r);
 }
 
+static void vg_hsv_rgb( v3f hsv, v3f rgb ){
+   i32 i = floorf( hsv[0]*6.0f );
+   f32 v = hsv[2],
+       f = hsv[0] * 6.0f - (f32)i,
+       p = v * (1.0f-hsv[1]),
+       q = v * (1.0f-f*hsv[1]),
+       t = v * (1.0f-(1.0f-f)*hsv[1]);
+
+   switch( i % 6 ){
+      case 0: rgb[0] = v; rgb[1] = t; rgb[2] = p; break;
+      case 1: rgb[0] = q; rgb[1] = v; rgb[2] = p; break;
+      case 2: rgb[0] = p; rgb[1] = v; rgb[2] = t; break;
+      case 3: rgb[0] = p; rgb[1] = q; rgb[2] = v; break;
+      case 4: rgb[0] = t; rgb[1] = p; rgb[2] = v; break;
+      case 5: rgb[0] = v; rgb[1] = p; rgb[2] = q; break;
+   }
+}
+
+static void vg_rgb_hsv( v3f rgb, v3f hsv ){
+   f32 min = v3_minf( rgb ),
+       max = v3_maxf( rgb ),
+       range = max-min,
+       k_epsilon = 0.00001f;
+
+   hsv[2] = max;
+   if( range < k_epsilon ){
+      hsv[0] = 0.0f;
+      hsv[1] = 0.0f;
+      return;
+   }
+
+   if( max > k_epsilon ){
+      hsv[1] = range/max;
+   }
+   else {
+      hsv[0] = 0.0f;
+      hsv[1] = 0.0f;
+      return;
+   }
+
+   if( rgb[0] >= max )
+      hsv[0] = (rgb[1]-rgb[2])/range;
+   else if( max == rgb[1] )
+      hsv[0] = 2.0f+(rgb[2]-rgb[0])/range;
+   else
+      hsv[0] = 4.0f+(rgb[0]-rgb[1])/range;
+
+   hsv[0] = vg_fractf( hsv[0] * (60.0f/360.0f) );
+}
+
 #endif /* VG_M_H */