colourpicker

Simple Colour Picker written in C
git clone anongit@rnpnr.xyz:colourpicker.git
Log | Files | Refs | Feed | Submodules | README | LICENSE

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 }