main.c (5914B)
1 /* See LICENSE for copyright details */ 2 #include <raylib.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 #include "util.c" 7 8 #ifdef _DEBUG 9 #include <dlfcn.h> 10 #include <fcntl.h> 11 #include <sys/stat.h> 12 #include <unistd.h> 13 14 typedef struct timespec Filetime; 15 16 global const char *libname = "./colourpicker.so"; 17 global void *libhandle; 18 19 typedef void (do_colour_picker_fn)(ColourPickerCtx *, f32 dt, Vector2 window_pos, Vector2 mouse); 20 global do_colour_picker_fn *do_colour_picker; 21 22 function Filetime 23 get_filetime(const char *name) 24 { 25 struct stat sb; 26 if (stat(name, &sb) < 0) 27 return (Filetime){0}; 28 return sb.st_mtim; 29 } 30 31 function s32 32 compare_filetime(Filetime a, Filetime b) 33 { 34 return (a.tv_sec - b.tv_sec) + (a.tv_nsec - b.tv_nsec); 35 } 36 37 function void 38 load_library(const char *lib) 39 { 40 /* NOTE: glibc is buggy gnuware so we need to check this */ 41 if (libhandle) 42 dlclose(libhandle); 43 libhandle = dlopen(lib, RTLD_NOW|RTLD_LOCAL); 44 if (!libhandle) 45 fprintf(stderr, "do_debug: dlopen: %s\n", dlerror()); 46 47 do_colour_picker = dlsym(libhandle, "do_colour_picker"); 48 if (!do_colour_picker) 49 fprintf(stderr, "do_debug: dlsym: %s\n", dlerror()); 50 } 51 52 function void 53 do_debug(void) 54 { 55 local_persist Filetime updated_time; 56 Filetime test_time = get_filetime(libname); 57 if (compare_filetime(test_time, updated_time)) { 58 load_library(libname); 59 updated_time = test_time; 60 } 61 62 } 63 #else 64 65 #define do_debug(...) 66 #include "colourpicker.c" 67 68 #endif /* _DEBUG */ 69 70 global const char *argv0; 71 72 function no_return void 73 usage(void) 74 { 75 printf("usage: %s [-h ????????] [-r ?.??] [-g ?.??] [-b ?.??] [-a ?.??]\n" 76 "\t-h: Hexadecimal Colour\n" 77 "\t-r|-g|-b|-a: Floating Point Colour Value\n", argv0); 78 exit(1); 79 } 80 81 function f64 82 try_read_f64(str8 s) 83 { 84 f64 result = 0; 85 NumberConversion number = number_from_str8(s); 86 if (number.result != NumberConversionResult_Success) { 87 printf("invalid float colour literal: %.*s\n", (s32)s.length, s.data); 88 usage(); 89 } 90 91 if (number.kind == NumberConversionKind_Float) result = number.F64; 92 else result = (f64)number.S64; 93 94 return result; 95 } 96 97 extern s32 98 main(s32 argc, char *argv[]) 99 { 100 argv0 = argv[0]; 101 102 ColourPickerCtx ctx = { 103 .window_size = { .w = 640, .h = 860 }, 104 105 .mode = CPM_PICKER, 106 .stored_colour_kind = ColourKind_HSV, 107 .flags = ColourPickerFlag_RefillTexture, 108 109 .text_input_state = {.idx = -1, .cursor_t = 1, .cursor_t_target = 0}, 110 .mcs = {.mode_visible_t = 1, .next_mode = -1}, 111 .ss = {.scale_t = {1, 1, 1, 1}}, 112 113 .bg = COLOUR_PICKER_BG, 114 .fg = COLOUR_PICKER_FG, 115 116 .colour = STARTING_COLOUR, 117 .hover_colour = HOVER_COLOUR, 118 .cursor_colour = CURSOR_COLOUR, 119 120 .colour_stack = { 121 .items = { 122 { .r = 0.04, .g = 0.04, .b = 0.04, .a = 1.00 }, 123 { .r = 0.92, .g = 0.88, .b = 0.78, .a = 1.00 }, 124 { .r = 0.34, .g = 0.23, .b = 0.50, .a = 1.00 }, 125 { .r = 0.59, .g = 0.11, .b = 0.25, .a = 1.00 }, 126 { .r = 0.20, .g = 0.60, .b = 0.24, .a = 1.00 }, 127 { .r = 0.14, .g = 0.29, .b = 0.72, .a = 1.00 }, 128 { .r = 0.11, .g = 0.59, .b = 0.36, .a = 1.00 }, 129 { .r = 0.72, .g = 0.37, .b = 0.19, .a = 1.00 }, 130 }, 131 }, 132 }; 133 134 for (u32 i = 0; i < CPM_LAST; i++) 135 ctx.mcs.buttons[i].hover_t = 1; 136 137 { 138 v4 rgb = hsv_to_rgb(ctx.colour); 139 for (s32 i = 1; i < argc; i++) { 140 if (argv[i][0] == '-') { 141 if (argv[i][1] == 'v') { 142 printf("colour picker %s\n", VERSION); 143 return 0; 144 } 145 if (argv[i + 1] == 0 || (argv[i][1] == 'h' && !IsHex(argv[i + 1][0]))) 146 usage(); 147 148 switch (argv[i][1]) { 149 case 'h':{ 150 NumberConversion number = integer_from_str8(str8_from_c_str(argv[i + 1]), 1); 151 if (number.result == NumberConversionResult_Success) { 152 rgb = normalize_colour(number.U64); 153 } else { 154 printf("invalid hexadecimal colour: %s\n", argv[i + 1]); 155 usage(); 156 } 157 ctx.colour = rgb_to_hsv(rgb); 158 }break; 159 case 'r':{rgb.r = try_read_f64(str8_from_c_str(argv[i + 1])); rgb.r = Clamp01(rgb.r);}break; 160 case 'g':{rgb.g = try_read_f64(str8_from_c_str(argv[i + 1])); rgb.g = Clamp01(rgb.g);}break; 161 case 'b':{rgb.b = try_read_f64(str8_from_c_str(argv[i + 1])); rgb.b = Clamp01(rgb.b);}break; 162 case 'a':{rgb.a = try_read_f64(str8_from_c_str(argv[i + 1])); rgb.a = Clamp01(rgb.a);}break; 163 default:{usage();}break; 164 } 165 i++; 166 } else { 167 usage(); 168 } 169 } 170 ctx.colour = rgb_to_hsv(rgb); 171 ctx.previous_colour = rgb; 172 } 173 ctx.pms.base_hue = ctx.colour.x; 174 175 #ifndef _DEBUG 176 SetTraceLogLevel(LOG_NONE); 177 #endif 178 179 SetConfigFlags(FLAG_VSYNC_HINT); 180 InitWindow(ctx.window_size.w, ctx.window_size.h, "Colour Picker"); 181 /* NOTE: do this after initing so that the window starts out floating in tiling wm */ 182 SetWindowMinSize(324, 324 * WINDOW_ASPECT_RATIO); 183 SetWindowState(FLAG_WINDOW_RESIZABLE); 184 185 { 186 Image icon; 187 RenderTexture icon_texture = LoadRenderTexture(128, 128); 188 BeginDrawing(); 189 BeginTextureMode(icon_texture); 190 ClearBackground(ctx.bg); 191 DrawCircleGradient(64, 64, 48, rl_colour_from_normalized(hsv_to_rgb(ctx.colour)), ctx.bg); 192 DrawRing((Vector2){64, 64}, 45, 48, 0, 360, 128, SELECTOR_BORDER_COLOUR); 193 EndTextureMode(); 194 EndDrawing(); 195 icon = LoadImageFromTexture(icon_texture.texture); 196 SetWindowIcon(icon); 197 UnloadRenderTexture(icon_texture); 198 UnloadImage(icon); 199 } 200 201 ctx.font = LoadFont_lora_sb_0_inc(); 202 203 while(!WindowShouldClose()) { 204 do_debug(); 205 206 BeginDrawing(); 207 ClearBackground(ctx.bg); 208 do_colour_picker(&ctx, GetFrameTime(), (Vector2){0}, GetMousePosition()); 209 EndDrawing(); 210 } 211 212 v4 rgba = {0}; 213 switch (ctx.stored_colour_kind) { 214 case ColourKind_RGB: rgba = ctx.colour; break; 215 case ColourKind_HSV: rgba = hsv_to_rgb(ctx.colour); break; 216 InvalidDefaultCase; 217 } 218 219 u32 packed_rgba = pack_rl_colour(rl_colour_from_normalized(rgba)); 220 printf("0x%08X|{.r = %0.03f, .g = %0.03f, .b = %0.03f, .a = %0.03f}\n", 221 packed_rgba, rgba.r, rgba.g, rgba.b, rgba.a); 222 223 return 0; 224 }