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