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
+++ /dev/null
-#include "Math_Utils.h"
-#include <math.h>
-
-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;
-}
-
+++ /dev/null
-#ifndef __MATH_UTILS__
-#define __MATH_UTILS__
-#include "structs.h"
-#include <math.h>
-
-#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__
-
-#if BUILD_SDL
-#include "sdl/SDL_Utils.h"
-#endif // BUILD_SDL
-
-#include "structs.h"
-#include "Math_Utils.h"
#include <sys/param.h>
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <assert.h>
-Game_Info gi;
+#include "rendering.h"
+#include "structs.h"
+
+runtime_info runtime;
void killterm_handler(int signum);
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;
};
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);
--- /dev/null
+#include <SDL2/SDL_ttf.h>
+#include <sys/param.h>
+
+#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
+}
+
#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__
+++ /dev/null
-#include <SDL2/SDL2_gfxPrimitives.h>
-#include <SDL2/SDL_ttf.h>
-#include <sys/param.h>
-
-#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
-}
-
#ifndef STRUCTS__
#define STRUCTS__
-#if BUILD_SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#define Point SDL_Point
#define Rect SDL_FRect
#define Relative_Rect SDL_FRect
#define Color SDL_Color
-#endif // BUILD_SDL
#include <stdint.h>
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__