main.c (5155B)
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 static const char *libname = "./libcolourpicker.so"; 17 static void *libhandle; 18 19 typedef void (do_colour_picker_fn)(ColourPickerCtx *, f32 dt, Vector2 window_pos, Vector2 mouse); 20 static do_colour_picker_fn *do_colour_picker; 21 22 static 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 static i32 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 static 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 static void 53 do_debug(void) 54 { 55 static Filetime updated_time; 56 Filetime test_time = get_filetime(libname); 57 if (compare_filetime(test_time, updated_time)) { 58 sync(); 59 load_library(libname); 60 updated_time = test_time; 61 } 62 63 } 64 #else 65 66 static void do_debug(void) { } 67 #include "colourpicker.c" 68 69 #endif /* _DEBUG */ 70 71 static void __attribute__((noreturn)) 72 usage(char *argv0) 73 { 74 printf("usage: %s [-h ????????] [-r ?.??] [-g ?.??] [-b ?.??] [-a ?.??]\n" 75 "\t-h: Hexadecimal Colour\n" 76 "\t-r|-g|-b|-a: Floating Point Colour Value\n", argv0); 77 exit(1); 78 } 79 80 int 81 main(i32 argc, char *argv[]) 82 { 83 ColourPickerCtx ctx = { 84 .window_size = { .w = 640, .h = 860 }, 85 86 .mode = CPM_PICKER, 87 .colour_mode = CM_HSV, 88 .flags = CPF_REFILL_TEXTURE, 89 90 91 .is = {.idx = -1, .cursor_t = 1, .cursor_t_target = 0}, 92 .mcs = {.mode_visible_t = 1, .next_mode = -1}, 93 .ss = {.scale_t = {1, 1, 1, 1}}, 94 95 .bg = COLOUR_PICKER_BG, 96 .fg = COLOUR_PICKER_FG, 97 98 .colour = STARTING_COLOUR, 99 .hover_colour = HOVER_COLOUR, 100 .cursor_colour = CURSOR_COLOUR, 101 102 .colour_stack = { 103 .items = { 104 { .r = 0.04, .g = 0.04, .b = 0.04, .a = 1.00 }, 105 { .r = 0.92, .g = 0.88, .b = 0.78, .a = 1.00 }, 106 { .r = 0.34, .g = 0.23, .b = 0.50, .a = 1.00 }, 107 { .r = 0.59, .g = 0.11, .b = 0.25, .a = 1.00 }, 108 { .r = 0.20, .g = 0.60, .b = 0.24, .a = 1.00 }, 109 { .r = 0.14, .g = 0.29, .b = 0.72, .a = 1.00 }, 110 { .r = 0.11, .g = 0.59, .b = 0.36, .a = 1.00 }, 111 { .r = 0.72, .g = 0.37, .b = 0.19, .a = 1.00 }, 112 }, 113 }, 114 }; 115 116 for (u32 i = 0; i < CPM_LAST; i++) 117 ctx.mcs.buttons[i].hover_t = 1; 118 119 { 120 v4 rgb = hsv_to_rgb(ctx.colour); 121 for (i32 i = 1; i < argc; i++) { 122 if (argv[i][0] == '-') { 123 if (argv[i][1] == 'v') { 124 printf("colour picker %s\n", VERSION); 125 return 0; 126 } 127 if (argv[i + 1] == NULL || 128 (argv[i][1] == 'h' && !ISHEX(argv[i + 1][0]))) 129 usage(argv[0]); 130 131 switch (argv[i][1]) { 132 case 'h': 133 rgb = normalize_colour(parse_hex_u32(argv[i + 1])); 134 ctx.colour = rgb_to_hsv(rgb); 135 break; 136 case 'r': rgb.r = parse_f32(argv[i + 1]); CLAMP01(rgb.r); break; 137 case 'g': rgb.g = parse_f32(argv[i + 1]); CLAMP01(rgb.g); break; 138 case 'b': rgb.b = parse_f32(argv[i + 1]); CLAMP01(rgb.b); break; 139 case 'a': rgb.a = parse_f32(argv[i + 1]); CLAMP01(rgb.a); break; 140 default: usage(argv[0]); break; 141 } 142 i++; 143 } else { 144 usage(argv[0]); 145 } 146 } 147 ctx.colour = rgb_to_hsv(rgb); 148 ctx.previous_colour = rgb; 149 } 150 ctx.pms.base_hue = ctx.colour.x; 151 152 #ifndef _DEBUG 153 SetTraceLogLevel(LOG_NONE); 154 #endif 155 156 SetConfigFlags(FLAG_VSYNC_HINT); 157 InitWindow(ctx.window_size.w, ctx.window_size.h, "Colour Picker"); 158 /* NOTE: do this after initing so that the window starts out floating in tiling wm */ 159 SetWindowMinSize(324, 324 * WINDOW_ASPECT_RATIO); 160 SetWindowState(FLAG_WINDOW_RESIZABLE); 161 162 { 163 Image icon; 164 RenderTexture icon_texture = LoadRenderTexture(128, 128); 165 BeginDrawing(); 166 BeginTextureMode(icon_texture); 167 ClearBackground(ctx.bg); 168 DrawCircleGradient(64, 64, 48, colour_from_normalized(hsv_to_rgb(ctx.colour)), ctx.bg); 169 DrawRing((Vector2){64, 64}, 45, 48, 0, 360, 128, SELECTOR_BORDER_COLOUR); 170 EndTextureMode(); 171 EndDrawing(); 172 icon = LoadImageFromTexture(icon_texture.texture); 173 SetWindowIcon(icon); 174 UnloadRenderTexture(icon_texture); 175 UnloadImage(icon); 176 } 177 178 ctx.font = LoadFont_lora_sb_0_inc(); 179 180 while(!WindowShouldClose()) { 181 do_debug(); 182 183 BeginDrawing(); 184 ClearBackground(ctx.bg); 185 do_colour_picker(&ctx, GetFrameTime(), (Vector2){0}, GetMousePosition()); 186 EndDrawing(); 187 } 188 189 v4 rgba = {0}; 190 switch (ctx.colour_mode) { 191 case CM_RGB: rgba = ctx.colour; break; 192 case CM_HSV: rgba = hsv_to_rgb(ctx.colour); break; 193 default: ASSERT(0); break; 194 } 195 196 u32 packed_rgba = pack_rl_colour(colour_from_normalized(rgba)); 197 printf("0x%08X|{.r = %0.03f, .g = %0.03f, .b = %0.03f, .a = %0.03f}\n", 198 packed_rgba, rgba.r, rgba.g, rgba.b, rgba.a); 199 200 return 0; 201 }