From: randy Date: Fri, 22 Sep 2023 02:17:23 +0000 (-0500) Subject: Big cleanup and refactoring. X-Git-Url: http://git.mcshandy.xyz/gitweb.cgi?a=commitdiff_plain;h=5fe0dc17b528e48854e13f41bb06da078a2f6c81;p=picker Big cleanup and refactoring. --- diff --git a/Makefile b/Makefile index 58f955f..1e72e9a 100755 --- a/Makefile +++ b/Makefile @@ -1,13 +1,11 @@ LIBS := -lm SOURCES := $(wildcard source/*.c) -SDL_SOURCES := $(wildcard source/sdl/*.c) -IMGUI_SOURCES = imgui/imgui.cpp imgui/imgui_impl_sdl.cpp imgui/imgui_impl_sdlrenderer.cpp imgui/imgui_tables.cpp imgui/imgui_widgets.cpp imgui/imgui_draw.cpp -picker: source/*.c source/*.h source/sdl/*.c source/sdl/*.h - gcc -DBUILD_SDL=1 $(SDL_SOURCES) $(SOURCES) $(LIBS) -lSDL2 -lSDL2_gfx -lSDL2_ttf -o bin/$@ +picker: source/*.c source/*.h + gcc $(SOURCES) $(LIBS) -lSDL2 -lSDL2_ttf -o bin/$@ -picker_debug: source/*.c source/*.h source/sdl/*.c source/sdl/*.h - gcc -g -DBUILD_SDL=1 $(SDL_SOURCES) $(SOURCES) $(LIBS) -lSDL2 -lSDL2_gfx -o bin/$@ +picker_debug: source/*.c source/*.h + gcc -g $(SOURCES) $(LIBS) -lSDL2 -lSDL2_ttf -o bin/$@ install: make picker diff --git a/source/Math_Utils.c b/source/Math_Utils.c deleted file mode 100644 index 847d8b9..0000000 --- a/source/Math_Utils.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "Math_Utils.h" -#include - -FPoint rotate(float theta, FPoint* vec) -{ - return (FPoint){vec->x * cos(theta) - vec->y * sin(theta), - vec->x * sin(theta) + vec->y * cos(theta)}; -} - -// root of sum of squared components -float magnitude(FPoint* vec) -{ - return sqrtf(pow(vec->x,2) + pow(vec->y, 2)); -} - -FPoint normalized(FPoint* vec) -{ - float mag = magnitude(vec); - return (FPoint){vec->x/mag, vec->y/mag}; -} - -float dot(const FPoint* left, const FPoint* right) -{ - return (left->x * right->x) + (left->y * right->y); -} - -FPoint mult(FPoint* vec, float mag) -{ - return (FPoint){vec->x * mag, vec->y * mag}; -} - -void mult_left(FPoint* vec, float mag) -{ - vec->x *= mag; vec->y *= mag; -} - -FPoint fp_add(FPoint* left, FPoint* right) -{ - return (FPoint){left->x + right->x, left->y + right->y}; -} - -void fp_add_left(FPoint* left, FPoint* right) -{ - left->x += right->x; - left->y += right->y; -} - -FPoint fp_sub(FPoint* left, FPoint* right) -{ - return (FPoint){left->x - right->x, left->y - right->y}; -} - -void fp_sub_left(FPoint* left, FPoint* right) -{ - left->x -= right->x; - left->y -= right->y; -} - diff --git a/source/Math_Utils.h b/source/Math_Utils.h deleted file mode 100644 index 2391306..0000000 --- a/source/Math_Utils.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __MATH_UTILS__ -#define __MATH_UTILS__ -#include "structs.h" -#include - -#define RAD_2_DEG(a) (float)a * (180.0f/M_PI) -#define DEG_2_RAD(a) (float)a * (M_PI/180.0f) - -FPoint rotate(float theta, FPoint* vec); -float magnitude(FPoint* vec); -FPoint normalized(FPoint* vec); -float dot(const FPoint* left, const FPoint* right); -FPoint mult(FPoint* vec, float mag); -void mult_left(FPoint* vec, float mag); -FPoint fp_add(FPoint* left, FPoint* right); -void fp_add_left(FPoint* left, FPoint* right); -FPoint fp_sub(FPoint* left, FPoint* right); -void fp_sub_left(FPoint* left, FPoint* right); - -#endif //__MATH_UTILS__ - diff --git a/source/main.c b/source/main.c index f707486..ecb2093 100644 --- a/source/main.c +++ b/source/main.c @@ -1,16 +1,13 @@ -#if BUILD_SDL -#include "sdl/SDL_Utils.h" -#endif // BUILD_SDL - -#include "structs.h" -#include "Math_Utils.h" #include #include #include #include #include -Game_Info gi; +#include "rendering.h" +#include "structs.h" + +runtime_info runtime; void killterm_handler(int signum); int init() @@ -20,33 +17,34 @@ int init() signal(SIGTERM, killterm_handler); float scale = 1.0f; - gi.window = (Rect){.x = 0.0f, .y = 0.0f, .w = scale*512.0f, .h = scale*512.0f}; + runtime.layout.window = (Rect){.x = 0.0f, .y = 0.0f, .w = scale*512.0f, .h = scale*512.0f}; // satisfying rel.[xy]*2 == .[wh] centers axis in parent container - gi.rgb_square.rel = (Rect){.x = 0.05, .y = 0.05, .w = 0.5, .h = 0.5}; - gi.hue_slider.rel = (Rect){.x = 0.65, .y = 0.05, .w = .08, .h = 0.5}; - gi.final_sample.rel = (Rect){.x = 0.05, .y = .65, .w = 0.20, .h = 0.20}; - gi.info_container.rel = (Rect){.x = 0.05, .y = .65, .w = .9, .h = .30}; - gi.info_boxes.rel = (Rect){.x = .25, .y = 0.00, .w = 0.75, .h = 1.00}; - gi.rgb_info.rel = (Rect){.x = 0.00, .y = 0.00, .w = 1.00, .h = 0.50}; - gi.red.rel = (Rect){.x = 0.00, .y = 0.00, .w = 0.30, .h = 1.00}; - gi.green.rel = (Rect){.x = 0.35, .y = 0.00, .w = 0.30, .h = 1.00}; - gi.blue.rel = (Rect){.x = 0.70, .y = 0.00, .w = 0.30, .h = 1.00}; - gi.hsl_info.rel = (Rect){.x = 0.00, .y = 0.50, .w = 1.00, .h = 0.50}; - gi.hue.rel = (Rect){.x = 0.00, .y = 0.00, .w = 0.30, .h = 1.00}; - gi.saturation.rel = (Rect){.x = 0.35, .y = 0.00, .w = 0.30, .h = 1.00}; - gi.luminence.rel = (Rect){.x = 0.70, .y = 0.00, .w = 0.30, .h = 1.00}; - - gi.active_hsl = (HSL_Color){.h = 0, .s = 100, .l = 50}; - gi.active_rgb = hsl_to_rgb(gi.active_hsl); + runtime.layout.rgb_square.rel = (Rect){.x = 0.05, .y = 0.05, .w = 0.5, .h = 0.5}; + runtime.layout.hue_slider.rel = (Rect){.x = 0.70, .y = 0.05, .w = .08, .h = 0.5}; + runtime.layout.final_sample.rel = (Rect){.x = 0.05, .y = .65, .w = 0.20, .h = 0.20}; + runtime.layout.info_container.rel = (Rect){.x = 0.05, .y = .65, .w = .9, .h = .30}; + runtime.layout.info_boxes.rel = (Rect){.x = .25, .y = 0.00, .w = 0.75, .h = 1.00}; + runtime.layout.rgb_info.rel = (Rect){.x = 0.00, .y = 0.00, .w = 1.00, .h = 0.50}; + runtime.layout.red.rel = (Rect){.x = 0.00, .y = 0.00, .w = 0.30, .h = 1.00}; + runtime.layout.green.rel = (Rect){.x = 0.35, .y = 0.00, .w = 0.30, .h = 1.00}; + runtime.layout.blue.rel = (Rect){.x = 0.70, .y = 0.00, .w = 0.30, .h = 1.00}; + runtime.layout.hsl_info.rel = (Rect){.x = 0.00, .y = 0.50, .w = 1.00, .h = 0.50}; + runtime.layout.hue.rel = (Rect){.x = 0.00, .y = 0.00, .w = 0.30, .h = 1.00}; + runtime.layout.saturation.rel = (Rect){.x = 0.35, .y = 0.00, .w = 0.30, .h = 1.00}; + runtime.layout.luminence.rel = (Rect){.x = 0.70, .y = 0.00, .w = 0.30, .h = 1.00}; + + runtime.active_hsl = (HSL_Color){.h = 0, .s = 100, .l = 50}; + runtime.active_rgb = hsl_to_rgb(runtime.active_hsl); TTF_Init(); - gi.font = TTF_OpenFont("/usr/share/fonts/TTF/iosevka-fixed-regular.ttf", 24); - assert(gi.font != NULL); + // Probably figure out how to get reliable fonts + runtime.font = TTF_OpenFont("/usr/share/fonts/TTF/iosevka-fixed-regular.ttf", 64); + assert(runtime.font != NULL); - init_renderer(&gi); + init_renderer(&runtime); - gi.game_alive = 1; + runtime.keep_alive = 1; return 0; }; @@ -63,13 +61,11 @@ int main(void) exit(__LINE__); } - while(gi.game_alive) + while(runtime.keep_alive) { clock_gettime(CLOCK_MONOTONIC_RAW, &ts_start); - - check_inputs(&gi); - display(&gi); - + check_inputs(&runtime); + display(&runtime); clock_gettime(CLOCK_MONOTONIC_RAW, &ts_end); uint64_t frameproc_ms = (ts_end.tv_nsec - ts_start.tv_nsec) / 1000000; frameproc_ms = MIN(time_step, frameproc_ms); diff --git a/source/rendering.c b/source/rendering.c new file mode 100644 index 0000000..ac75174 --- /dev/null +++ b/source/rendering.c @@ -0,0 +1,341 @@ +#include +#include + +#include "rendering.h" + +#define unroll_sdl_color(color) color.r, color.g, color.b, color.a + +SDL_Color red = {255, 0, 0, 255}; +SDL_Color green = {0, 255, 0, 255}; +SDL_Color blue = {0, 0, 255, 255}; +SDL_Color black = {0, 0, 0, 255}; +SDL_Color white = {255, 255, 255, 255}; +SDL_Color magenta = {255, 0, 255, 255}; + +sdl_group mgr; +const int keypress_delta = 4; + +int32_t init_renderer(runtime_info* runtime) +{ + //load_config(argv[1], gs); + + SDL_SetMainReady(); + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER)) + { + fprintf(stderr, "SDL initialization failed\n"); + exit(__LINE__); + } + + mgr.win = SDL_CreateWindow("Color Picker", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, runtime->layout.window.w, runtime->layout.window.h, 0); + if (mgr.win == NULL) + { + fprintf(stderr, "SDL initialization failed\n"); + exit(__LINE__); + } + + mgr.rend = SDL_CreateRenderer(mgr.win, -1, SDL_RENDERER_ACCELERATED); + if (mgr.rend == NULL) + { + fprintf(stderr, "SDL initialization failed\n"); + exit(__LINE__); + } + + SDL_SetRenderDrawBlendMode(mgr.rend, SDL_BLENDMODE_BLEND); + + // this would be really cool to turn into some stack-based type of thing + // Also, if resizing is disabled, this can be moved to a static initialization section + // orrrr, maybe we can finally do callbacks + render_container(runtime, &runtime->layout.window, &runtime->layout.rgb_square, green); + render_container(runtime, &runtime->layout.window, &runtime->layout.hue_slider, green); + render_container(runtime, &runtime->layout.window, &runtime->layout.info_container, blue); + render_container(runtime, &runtime->layout.window, &runtime->layout.final_sample, green); + render_container(runtime, &runtime->layout.info_container.real, &runtime->layout.info_boxes, green); + render_container(runtime, &runtime->layout.info_boxes.real, &runtime->layout.rgb_info, black); + render_container(runtime, &runtime->layout.rgb_info.real, &runtime->layout.red, red); + render_container(runtime, &runtime->layout.rgb_info.real, &runtime->layout.green, green); + render_container(runtime, &runtime->layout.rgb_info.real, &runtime->layout.blue, blue); + render_container(runtime, &runtime->layout.info_boxes.real, &runtime->layout.hsl_info, white); + render_container(runtime, &runtime->layout.hsl_info.real, &runtime->layout.hue, green); + render_container(runtime, &runtime->layout.hsl_info.real, &runtime->layout.saturation, blue); + render_container(runtime, &runtime->layout.hsl_info.real, &runtime->layout.luminence, red); +} + +int32_t shutdown_renderer() +{ + SDL_DestroyRenderer(mgr.rend); + SDL_DestroyWindow(mgr.win); + SDL_Quit(); +} + +int32_t delay(int32_t delay_time) +{ + SDL_Delay(delay_time); + + return 0; +} + +// Rename this eventually +// It's actually HSL +int32_t render_rgb_square(runtime_info* runtime, SDL_FRect* container) +{ + HSL_Color active_hsl = runtime->active_hsl; + SDL_Color hsl_pixel; + SDL_Point draw_point; + SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(runtime->active_rgb)); + SDL_RenderFillRectF(mgr.rend, container); + + // I guess not much other way than good ol' n^2 + // hmmm we'll fix this later + + active_hsl.s = 0; + active_hsl.l = 0; + for (int r = 0; r < container->w; r++) + { + active_hsl.s = ((float)r/(float)container->w) * 100; + for (int c = 0; c < container->h; c++) + { + active_hsl.l = ((float)1.0-c/(float)container->h) * 100; + + hsl_pixel = hsl_to_rgb(active_hsl); + SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(hsl_pixel)); + SDL_RenderDrawPoint(mgr.rend, r+container->x, c+container->y); + } + } + + float s_norm = (float)runtime->active_hsl.s/100.0f; + float l_norm = (float)runtime->active_hsl.l/100.0f; + SDL_Rect cursor = { + .x = ((s_norm) * container->w) + container->x, + .y = ((1.0f - l_norm) * container->h) + container->y, + .w = 10, + .h = 10 + }; + SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(black)); + SDL_RenderDrawLine(mgr.rend, container->x-16, cursor.y, container->x+container->w+16, cursor.y); + SDL_RenderDrawLine(mgr.rend, cursor.x, container->y-16, cursor.x, container->y+container->h+16); + + return 0; +} + +int32_t render_color_preview(runtime_info* runtime, SDL_FRect* container) +{ + runtime->active_rgb = hsl_to_rgb(runtime->active_hsl); + SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(runtime->active_rgb)); + SDL_RenderFillRectF(mgr.rend, container); + + return 0; +} + +// https://stackoverflow.com/questions/22886500/how-to-render-text-in-sdl2 +// This is horrible horrible horrible +int32_t render_info_boxes(runtime_info* runtime, SDL_FRect* container) +{ + char red_string[32]; + char blu_string[32]; + char grn_string[32]; + char hue_string[32]; + char sat_string[32]; + char lum_string[32]; + + sprintf(red_string, "R:%d/%X", runtime->active_rgb.r, runtime->active_rgb.r); + sprintf(grn_string, "G:%d/%X", runtime->active_rgb.g, runtime->active_rgb.g); + sprintf(blu_string, "B:%d/%X", runtime->active_rgb.b, runtime->active_rgb.b); + sprintf(hue_string, "H:%d/%X", runtime->active_hsl.h, runtime->active_hsl.h); + sprintf(sat_string, "S:%d/%X", runtime->active_hsl.s, runtime->active_hsl.s); + sprintf(lum_string, "L:%d/%X", runtime->active_hsl.l, runtime->active_hsl.l); + + runtime->layout.red_component_text_surface = TTF_RenderText_Solid(runtime->font, red_string, black); + runtime->layout.green_component_text_surface = TTF_RenderText_Solid(runtime->font, grn_string, black); + runtime->layout.blue_component_text_surface = TTF_RenderText_Solid(runtime->font, blu_string, black); + runtime->layout.hue_component_text_surface = TTF_RenderText_Solid(runtime->font, hue_string, black); + runtime->layout.sat_component_text_surface = TTF_RenderText_Solid(runtime->font, sat_string, black); + runtime->layout.lum_component_text_surface = TTF_RenderText_Solid(runtime->font, lum_string, black); + + runtime->layout.red_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, runtime->layout.red_component_text_surface); + runtime->layout.green_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, runtime->layout.green_component_text_surface); + runtime->layout.blue_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, runtime->layout.blue_component_text_surface); + runtime->layout.hue_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, runtime->layout.hue_component_text_surface); + runtime->layout.sat_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, runtime->layout.sat_component_text_surface); + runtime->layout.lum_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, runtime->layout.lum_component_text_surface); + + // Now we can render + SDL_RenderCopyF(mgr.rend, runtime->layout.red_component_text_tex, NULL, &runtime->layout.red.real); + SDL_RenderCopyF(mgr.rend, runtime->layout.green_component_text_tex, NULL, &runtime->layout.green.real); + SDL_RenderCopyF(mgr.rend, runtime->layout.blue_component_text_tex, NULL, &runtime->layout.blue.real); + SDL_RenderCopyF(mgr.rend, runtime->layout.hue_component_text_tex, NULL, &runtime->layout.hue.real); + SDL_RenderCopyF(mgr.rend, runtime->layout.sat_component_text_tex, NULL, &runtime->layout.saturation.real); + SDL_RenderCopyF(mgr.rend, runtime->layout.lum_component_text_tex, NULL, &runtime->layout.luminence.real); + + // Cleanup + SDL_FreeSurface(runtime->layout.red_component_text_surface); + SDL_FreeSurface(runtime->layout.green_component_text_surface); + SDL_FreeSurface(runtime->layout.blue_component_text_surface); + SDL_FreeSurface(runtime->layout.hue_component_text_surface); + SDL_FreeSurface(runtime->layout.sat_component_text_surface); + SDL_FreeSurface(runtime->layout.lum_component_text_surface); + + SDL_DestroyTexture(runtime->layout.red_component_text_tex); + SDL_DestroyTexture(runtime->layout.green_component_text_tex); + SDL_DestroyTexture(runtime->layout.blue_component_text_tex); + SDL_DestroyTexture(runtime->layout.hue_component_text_tex); + SDL_DestroyTexture(runtime->layout.sat_component_text_tex); + SDL_DestroyTexture(runtime->layout.lum_component_text_tex); +} + +int32_t render_vertical_hue_spectrum(runtime_info* runtime, SDL_FRect* container) +{ + + int hue_slice_scale = container->h; + float hue_slice_height = hue_slice_scale/360.0f; + + int bar_y = runtime->active_hsl.h/360.0f*container->h + container->y; + SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(black)); + SDL_RenderDrawLine(mgr.rend, container->x-16, bar_y, container->w+container->x+16, bar_y); + + for (int n = 0; n < (int)container->h; n++) + { + HSL_Color slice_hsl = {((float)n/(float)container->h) * 360, 100, 50}; + SDL_Color slice_color = hsl_to_rgb (slice_hsl); + + SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(slice_color)); + SDL_RenderDrawLine(mgr.rend, container->x, container->y + n, container->w+container->x, container->y+n); + } + + return 0; +} + +// REALLY this should be "generate layout", and not a true rendering step +int32_t render_container(runtime_info* runtime, SDL_FRect* parent, Layout_Rect* child, SDL_Color color) +{ + SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(color)); + child->real = fr_marruntimen_adjust(*parent, child->rel); + + return 0; +} + +int32_t display(runtime_info* runtime) +{ + SDL_SetRenderDrawColor(mgr.rend, 0xCB, 0xCB, 0xCB, 0xCB); + SDL_RenderClear(mgr.rend); + + runtime->active_rgb = hsl_to_rgb(runtime->active_hsl); + + render_color_preview(runtime, &runtime->layout.final_sample.real); + render_vertical_hue_spectrum(runtime, &runtime->layout.hue_slider.real); + render_rgb_square(runtime, &runtime->layout.rgb_square.real); + render_info_boxes(runtime, &runtime->layout.info_boxes.real); + + SDL_RenderPresent(mgr.rend); + return 0; +} + +int32_t check_inputs(runtime_info* runtime) +{ + while(SDL_PollEvent(&(mgr.event))) + { + if (mgr.event.type == SDL_KEYDOWN) + { + switch(mgr.event.key.keysym.sym) + { + case SDLK_q: + runtime->keep_alive = 0; + break; + case SDLK_b: + runtime->active_hsl.h += 1; + if(runtime->active_hsl.h > 360) + runtime->active_hsl.h -= 360; + break; + case SDLK_n: + runtime->active_hsl.h -= 1; + if(runtime->active_hsl.h < 0) + runtime->active_hsl.h += 360; + break; + case SDLK_k: + if(runtime->active_hsl.l < 100) + runtime->active_hsl.l += 1; + break; + case SDLK_j: + if(runtime->active_hsl.l > 0) + runtime->active_hsl.l -= 1; + break; + case SDLK_l: + if(runtime->active_hsl.s < 100) + runtime->active_hsl.s += 1; + break; + case SDLK_h: + if(runtime->active_hsl.s > 0) + runtime->active_hsl.s -= 1; + break; + } + } + } + + return 0; +} + +SDL_FRect fr_subtract(const SDL_FRect left, const SDL_FRect right) +{ + return + (SDL_FRect){ + left.x - right.x, + left.y - right.y, + left.w - right.w, + left.h - right.h + }; +} + +SDL_FRect fr_add(const SDL_FRect left, const SDL_FRect right) +{ + return + (SDL_FRect){ + left.x + right.x, + left.y + right.y, + left.w + right.w, + left.h + right.h + }; +} + +SDL_FRect fr_mult(const SDL_FRect left, const SDL_FRect right) +{ + return + (SDL_FRect){ + left.x * right.x, + left.y * right.y, + left.w * right.w, + left.h * right.h + }; +} + +// Math out placement for a relative rect onto a concrete parent +SDL_FRect fr_marruntimen_adjust(const SDL_FRect parent, const Relative_Rect child) +{ + return + (SDL_FRect){ + .x = parent.x + ( parent.w * (child.x ) ), + .y = parent.y + ( parent.h * (child.y ) ), + + .w = parent.w * child.w, + .h = parent.h * child.h, + }; +} + +float hsl_to_rgb_alt_internal(const HSL_Color hsl, int n) +{ + float H = (float)hsl.h; + float L = (float)hsl.l/100.0f; + float S = (float)hsl.s/100.0f; + float a = S * MIN(L, 1-L); + float k = fmod((n + (H/30.0)), 12.0); + return L - a * MAX(-1, MIN(k-3, MIN(9-k, 1))); +} + +// https://www.wikiwand.com/en/HSL_and_HSV#To_RGB +SDL_Color hsl_to_rgb (const HSL_Color hsl) +{ + return (SDL_Color){ + .r = (uint8_t)(hsl_to_rgb_alt_internal(hsl, 0) * 255), + .g = (uint8_t)(hsl_to_rgb_alt_internal(hsl, 8) * 255), + .b = (uint8_t)(hsl_to_rgb_alt_internal(hsl, 4) * 255), + .a = 0xFF}; // Opaque +} + diff --git a/source/sdl/SDL_Utils.h b/source/rendering.h similarity index 60% rename from source/sdl/SDL_Utils.h rename to source/rendering.h index 7631c08..8394993 100644 --- a/source/sdl/SDL_Utils.h +++ b/source/rendering.h @@ -1,28 +1,27 @@ #ifndef SDL_Utils__ #define SDL_Utils__ -#include "../structs.h" +#include "structs.h" typedef struct sdl_group { SDL_Window* win; SDL_Renderer* rend; - SDL_Texture* text; SDL_Event event; - - SDL_GameController* pad; } sdl_group; -int32_t init_renderer(Game_Info* gi); +int32_t init_renderer(runtime_info* runtime); int32_t shutdown_renderer(); int32_t delay(int32_t delay_time); -int32_t display(Game_Info* gi); -int32_t check_inputs(Game_Info* gi); +int32_t display(runtime_info* runtime); +int32_t check_inputs(runtime_info* runtime); + +int32_t render_container(runtime_info* runtime, SDL_FRect* parent, Layout_Rect* child, SDL_Color color); SDL_FRect fr_add(const SDL_FRect left, const SDL_FRect right); SDL_FRect fr_subtract(const SDL_FRect left, const SDL_FRect right); SDL_FRect fr_mult(const SDL_FRect left, const SDL_FRect right); -SDL_FRect fr_margin_adjust(const SDL_FRect parent, const Relative_Rect child); +SDL_FRect fr_marruntimen_adjust(const SDL_FRect parent, const Relative_Rect child); SDL_Color hsl_to_rgb (const HSL_Color hsl); SDL_Color wikipedia_hsl_to_rgb (const HSL_Color hsl); #endif // SDL_Utils__ diff --git a/source/sdl/SDL_Utils.c b/source/sdl/SDL_Utils.c deleted file mode 100644 index 9746252..0000000 --- a/source/sdl/SDL_Utils.c +++ /dev/null @@ -1,352 +0,0 @@ -#include -#include -#include - -#include "SDL_Utils.h" -#include "../Math_Utils.h" - -#define unroll_sdl_color(color) color.r, color.g, color.b, color.a - -SDL_Color red = {255, 0, 0, 255}; -SDL_Color green = {0, 255, 0, 255}; -SDL_Color blue = {0, 0, 255, 255}; -SDL_Color black = {0, 0, 0, 255}; -SDL_Color white = {255, 255, 255, 255}; -SDL_Color magenta = {255, 0, 255, 255}; - -sdl_group mgr; -const int keypress_delta = 4; - -int32_t init_renderer(Game_Info* gi) -{ - mgr.pad = NULL; - - //load_config(argv[1], gs); - - SDL_SetMainReady(); - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER)) - { - fprintf(stderr, "SDL initialization failed\n"); - exit(__LINE__); - } - - mgr.win = SDL_CreateWindow("Color Picker", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, gi->window.w, gi->window.h, 0); - if (mgr.win == NULL) - { - fprintf(stderr, "SDL initialization failed\n"); - exit(__LINE__); - } - - mgr.rend = SDL_CreateRenderer(mgr.win, -1, SDL_RENDERER_ACCELERATED); - if (mgr.rend == NULL) - { - fprintf(stderr, "SDL initialization failed\n"); - exit(__LINE__); - } - - SDL_SetRenderDrawBlendMode(mgr.rend, SDL_BLENDMODE_BLEND); -} - -int32_t shutdown_renderer() -{ - SDL_DestroyRenderer(mgr.rend); - SDL_DestroyWindow(mgr.win); - SDL_Quit(); -} - -int32_t delay(int32_t delay_time) -{ - SDL_Delay(delay_time); - - return 0; -} - -// Rename this eventually -// It's actually HSL -int32_t render_rgb_square(Game_Info* gi, SDL_FRect* container) -{ - HSL_Color active_hsl = gi->active_hsl; - SDL_Color hsl_pixel; - SDL_Point draw_point; - SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(gi->active_rgb)); - SDL_RenderFillRectF(mgr.rend, container); - - // I guess not much other way than good ol' n^2 - // hmmm we'll fix this later - - active_hsl.s = 0; - active_hsl.l = 0; - for (int r = 0; r < container->w; r++) - { - active_hsl.s = ((float)r/(float)container->w) * 100; - for (int c = 0; c < container->h; c++) - { - active_hsl.l = ((float)1.0-c/(float)container->h) * 100; - - hsl_pixel = hsl_to_rgb(active_hsl); - SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(hsl_pixel)); - SDL_RenderDrawPoint(mgr.rend, r+container->x, c+container->y); - } - } - - float s_norm = (float)gi->active_hsl.s/100.0f; - float l_norm = (float)gi->active_hsl.l/100.0f; - SDL_Rect cursor = { - .x = ((s_norm) * container->w) + container->x, - .y = ((1.0f - l_norm) * container->h) + container->y, - .w = 10, - .h = 10 - }; - SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(black)); - SDL_RenderDrawLine(mgr.rend, container->x-16, cursor.y, container->x+container->w+16, cursor.y); - SDL_RenderDrawLine(mgr.rend, cursor.x, container->y-16, cursor.x, container->y+container->h+16); - - return 0; -} - -int32_t render_color_preview(Game_Info* gi, SDL_FRect* container) -{ - gi->active_rgb = hsl_to_rgb(gi->active_hsl); - SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(gi->active_rgb)); - SDL_RenderFillRectF(mgr.rend, container); - - return 0; -} - -// https://stackoverflow.com/questions/22886500/how-to-render-text-in-sdl2 -// This is horrible and textures should really be cached in some way -int32_t render_info_boxes(Game_Info* gi, SDL_FRect* container) -{ - char red_string[32]; - char blu_string[32]; - char grn_string[32]; - char hue_string[32]; - char sat_string[32]; - char lum_string[32]; - - sprintf(red_string, "R:%d/%X", gi->active_rgb.r, gi->active_rgb.r); - sprintf(grn_string, "G:%d/%X", gi->active_rgb.g, gi->active_rgb.g); - sprintf(blu_string, "B:%d/%X", gi->active_rgb.b, gi->active_rgb.b); - sprintf(hue_string, "H:%d/%X", gi->active_hsl.h, gi->active_hsl.h); - sprintf(sat_string, "S:%d/%X", gi->active_hsl.s, gi->active_hsl.s); - sprintf(lum_string, "L:%d/%X", gi->active_hsl.l, gi->active_hsl.l); - - gi->red_component_text_surface = TTF_RenderText_Solid(gi->font, red_string, black); - gi->green_component_text_surface = TTF_RenderText_Solid(gi->font, grn_string, black); - gi->blue_component_text_surface = TTF_RenderText_Solid(gi->font, blu_string, black); - gi->hue_component_text_surface = TTF_RenderText_Solid(gi->font, hue_string, black); - gi->sat_component_text_surface = TTF_RenderText_Solid(gi->font, sat_string, black); - gi->lum_component_text_surface = TTF_RenderText_Solid(gi->font, lum_string, black); - - gi->red_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, gi->red_component_text_surface); - gi->green_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, gi->green_component_text_surface); - gi->blue_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, gi->blue_component_text_surface); - gi->hue_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, gi->hue_component_text_surface); - gi->sat_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, gi->sat_component_text_surface); - gi->lum_component_text_tex = SDL_CreateTextureFromSurface(mgr.rend, gi->lum_component_text_surface); - - // Now we can render - SDL_RenderCopyF(mgr.rend, gi->red_component_text_tex, NULL, &gi->red.real); - SDL_RenderCopyF(mgr.rend, gi->green_component_text_tex, NULL, &gi->green.real); - SDL_RenderCopyF(mgr.rend, gi->blue_component_text_tex, NULL, &gi->blue.real); - SDL_RenderCopyF(mgr.rend, gi->hue_component_text_tex, NULL, &gi->hue.real); - SDL_RenderCopyF(mgr.rend, gi->sat_component_text_tex, NULL, &gi->saturation.real); - SDL_RenderCopyF(mgr.rend, gi->lum_component_text_tex, NULL, &gi->luminence.real); - - // Cleanup - SDL_FreeSurface(gi->red_component_text_surface); - SDL_FreeSurface(gi->green_component_text_surface); - SDL_FreeSurface(gi->blue_component_text_surface); - SDL_FreeSurface(gi->hue_component_text_surface); - SDL_FreeSurface(gi->sat_component_text_surface); - SDL_FreeSurface(gi->lum_component_text_surface); - SDL_DestroyTexture(gi->red_component_text_tex); - SDL_DestroyTexture(gi->green_component_text_tex); - SDL_DestroyTexture(gi->blue_component_text_tex); - SDL_DestroyTexture(gi->hue_component_text_tex); - SDL_DestroyTexture(gi->sat_component_text_tex); - SDL_DestroyTexture(gi->lum_component_text_tex); -} - -int32_t render_vertical_hue_spectrum(Game_Info* gi, SDL_FRect* container) -{ - - int hue_slice_scale = container->h; - float hue_slice_height = hue_slice_scale/360.0f; - - int bar_y = gi->active_hsl.h/360.0f*container->h + container->y; - SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(black)); - SDL_RenderDrawLine(mgr.rend, container->x-16, bar_y, container->w+container->x+16, bar_y); - - for (int n = 0; n < (int)container->h; n++) - { - HSL_Color slice_hsl = {((float)n/(float)container->h) * 360, 100, 50}; - SDL_Color slice_color = hsl_to_rgb (slice_hsl); - - SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(slice_color)); - SDL_RenderDrawLine(mgr.rend, container->x, container->y + n, container->w+container->x, container->y+n); - } - - return 0; -} - -// REALLY this should be "generate layout", and not a true rendering step -// For now just do the math and color the full space of the child -int32_t render_container(Game_Info* gi, SDL_FRect* parent, Layout_Rect* child, SDL_Color color) -{ - SDL_SetRenderDrawColor(mgr.rend, unroll_sdl_color(color)); - child->real = fr_margin_adjust(*parent, child->rel); - //SDL_RenderFillRectF(mgr.rend, &child->real); - - return 0; -} - -int32_t display(Game_Info* gi) -{ - SDL_SetRenderDrawColor(mgr.rend, 0xCB, 0xCB, 0xCB, 0xCB); - SDL_RenderClear(mgr.rend); - - gi->active_rgb = hsl_to_rgb(gi->active_hsl); - - // this would be really cool to turn into some stack-based type of thing - // Also, if resizing is disabled, this can be moved to a static initialization section - // orrrr, maybe we can finally do callbacks - render_container(gi, &gi->window, &gi->rgb_square, green); - render_container(gi, &gi->window, &gi->hue_slider, green); - render_container(gi, &gi->window, &gi->info_container, blue); - render_container(gi, &gi->window, &gi->final_sample, green); - render_container(gi, &gi->info_container.real, &gi->info_boxes, green); - render_container(gi, &gi->info_boxes.real, &gi->rgb_info, black); - render_container(gi, &gi->rgb_info.real, &gi->red, red); - render_container(gi, &gi->rgb_info.real, &gi->green, green); - render_container(gi, &gi->rgb_info.real, &gi->blue, blue); - render_container(gi, &gi->info_boxes.real, &gi->hsl_info, white); - render_container(gi, &gi->hsl_info.real, &gi->hue, green); - render_container(gi, &gi->hsl_info.real, &gi->saturation, blue); - render_container(gi, &gi->hsl_info.real, &gi->luminence, red); - - render_color_preview(gi, &gi->final_sample.real); - render_vertical_hue_spectrum(gi, &gi->hue_slider.real); - render_rgb_square(gi, &gi->rgb_square.real); - render_info_boxes(gi, &gi->info_boxes.real); - - SDL_RenderPresent(mgr.rend); - return 0; -} - -int32_t check_inputs(Game_Info* gi) -{ - while(SDL_PollEvent(&(mgr.event))) - { - if (mgr.event.type == SDL_KEYDOWN) - { - switch(mgr.event.key.keysym.sym) - { - case SDLK_q: - gi->game_alive = 0; - break; - case SDLK_b: - gi->active_hsl.h += 1; - if(gi->active_hsl.h > 360) - gi->active_hsl.h -= 360; - break; - case SDLK_n: - gi->active_hsl.h -= 1; - if(gi->active_hsl.h < 0) - gi->active_hsl.h += 360; - break; - case SDLK_k: - if(gi->active_hsl.l < 100) - gi->active_hsl.l += 1; - break; - case SDLK_j: - if(gi->active_hsl.l > 0) - gi->active_hsl.l -= 1; - break; - case SDLK_l: - if(gi->active_hsl.s < 100) - gi->active_hsl.s += 1; - break; - case SDLK_h: - if(gi->active_hsl.s > 0) - gi->active_hsl.s -= 1; - break; - } - } - } - - // controller support later - if(mgr.pad) - { - // update_for_controller(mgr, gs); - } - - return 0; -} - -SDL_FRect fr_subtract(const SDL_FRect left, const SDL_FRect right) -{ - return - (SDL_FRect){ - left.x - right.x, - left.y - right.y, - left.w - right.w, - left.h - right.h - }; -} - -SDL_FRect fr_add(const SDL_FRect left, const SDL_FRect right) -{ - return - (SDL_FRect){ - left.x + right.x, - left.y + right.y, - left.w + right.w, - left.h + right.h - }; -} - -SDL_FRect fr_mult(const SDL_FRect left, const SDL_FRect right) -{ - return - (SDL_FRect){ - left.x * right.x, - left.y * right.y, - left.w * right.w, - left.h * right.h - }; -} - -// Math out placement for a relative rect onto a concrete parent -SDL_FRect fr_margin_adjust(const SDL_FRect parent, const Relative_Rect child) -{ - return - (SDL_FRect){ - .x = parent.x + ( parent.w * (child.x ) ), - .y = parent.y + ( parent.h * (child.y ) ), - - .w = parent.w * child.w, - .h = parent.h * child.h, - }; -} - -float hsl_to_rgb_alt_internal(const HSL_Color hsl, int n) -{ - float H = (float)hsl.h; - float L = (float)hsl.l/100.0f; - float S = (float)hsl.s/100.0f; - float a = S * MIN(L, 1-L); - float k = fmod((n + (H/30.0)), 12.0); - return L - a * MAX(-1, MIN(k-3, MIN(9-k, 1))); -} - -// https://www.wikiwand.com/en/HSL_and_HSV#To_RGB -SDL_Color hsl_to_rgb (const HSL_Color hsl) -{ - return (SDL_Color){ - .r = (uint8_t)(hsl_to_rgb_alt_internal(hsl, 0) * 255), - .g = (uint8_t)(hsl_to_rgb_alt_internal(hsl, 8) * 255), - .b = (uint8_t)(hsl_to_rgb_alt_internal(hsl, 4) * 255), - .a = 0xFF}; // Opaque -} - diff --git a/source/structs.h b/source/structs.h index 9cfbcfc..dc476cf 100644 --- a/source/structs.h +++ b/source/structs.h @@ -1,7 +1,6 @@ #ifndef STRUCTS__ #define STRUCTS__ -#if BUILD_SDL #include #include #define Point SDL_Point @@ -9,7 +8,6 @@ #define Rect SDL_FRect #define Relative_Rect SDL_FRect #define Color SDL_Color -#endif // BUILD_SDL #include @@ -77,14 +75,19 @@ typedef struct SDL_Surface* lum_component_text_surface; SDL_Texture* lum_component_text_tex; +} Window_Layout; + +typedef struct +{ Color active_rgb; HSL_Color active_hsl; + Window_Layout layout; - int game_alive; + int keep_alive; TTF_Font* font; -} Game_Info; +} runtime_info; #endif // STRUCTS__