colourpicker

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

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 }