From 12626a513eb60e0feb104341ec76ddd71bb10fd1 Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Tue, 9 Jan 2024 01:13:01 +0200 Subject: [PATCH] zephr/ui: dynamically determine color picker buttons' text color and crosshairs selection's color --- game.c | 2 +- ui.c | 41 +++++++++++++++++++++++++++++++---------- ui.h | 4 +++- zephr.c | 10 ++++------ zephr.h | 1 - zephr_math.c | 25 +++++++++++++++++++++++++ zephr_math.h | 3 +++ 7 files changed, 67 insertions(+), 19 deletions(-) diff --git a/game.c b/game.c index 61775df..b97e36f 100644 --- a/game.c +++ b/game.c @@ -645,7 +645,7 @@ void draw_settings_dialog(void) { set_y_constraint(&color_picker_con, 320 - text_size.height / 2.f + 6, UI_CONSTRAINT_RELATIVE_PIXELS); set_width_constraint(&color_picker_con, tile_size, UI_CONSTRAINT_RELATIVE_PIXELS); set_height_constraint(&color_picker_con, tile_size, UI_CONSTRAINT_RELATIVE_PIXELS); - draw_color_picker(&color_picker_con, &game.palette.tile_colors[i], ALIGN_TOP_LEFT, BUTTON_STATE_ACTIVE); + draw_color_picker_with_id(i, &color_picker_con, &game.palette.tile_colors[i], ALIGN_TOP_LEFT, BUTTON_STATE_ACTIVE); u16 tile_val = (u16)pow(2, i + 1); char text[16]; diff --git a/ui.c b/ui.c index cd86d0c..6f8a3c7 100644 --- a/ui.c +++ b/ui.c @@ -630,7 +630,7 @@ f32 draw_color_picker_slider_with_location(const char *file, int line, UIConstra #define draw_color_picker_canvas(constraints, slider_percentage, align) draw_color_picker_canvas_with_location(__FILE__, __LINE__, constraints, slider_percentage, align) -Vec2f draw_color_picker_canvas_with_location(const char* file, int line, UIConstraints *constraints, f32 slider_percentage, Alignment align) { +Color draw_color_picker_canvas_with_location(const char* file, int line, UIConstraints *constraints, f32 slider_percentage, Alignment align) { static bool dragging = false; static Vec2f canvas_pos = {0}; @@ -703,6 +703,8 @@ Vec2f draw_color_picker_canvas_with_location(const char* file, int line, UIConst glBindVertexArray(0); + Color selected_color = hsv2rgb(slider_percentage * 360.f, canvas_pos.x, 1.0f - canvas_pos.y); + // draw the selection UIConstraints triangle_con = default_constraints; set_parent_constraint(&triangle_con, constraints); @@ -711,10 +713,10 @@ Vec2f draw_color_picker_canvas_with_location(const char* file, int line, UIConst set_width_constraint(&triangle_con, 14, UI_CONSTRAINT_RELATIVE_PIXELS); set_height_constraint(&triangle_con, 0.5f, UI_CONSTRAINT_ASPECT_RATIO); triangle_con.x -= triangle_con.height; - triangle_con.y -= triangle_con.height * 2; + triangle_con.y -= triangle_con.height + triangle_con.height / 2 + triangle_con.width / 2; set_rotation_constraint(&triangle_con, 0); UiStyle tri_style = { - .bg_color = COLOR_WHITE, + .bg_color = determine_color_contrast(&selected_color), .border_radius = 0, .align = ALIGN_TOP_LEFT, }; @@ -735,7 +737,7 @@ Vec2f draw_color_picker_canvas_with_location(const char* file, int line, UIConst set_rotation_constraint(&triangle_con, 270); draw_triangle(&triangle_con, tri_style); - return canvas_pos; + return selected_color; } // TODO: consume mouse events on the popup @@ -764,7 +766,7 @@ void draw_color_picker_popup(UIConstraints *picker_button_con) { set_x_constraint(&color_slider_con, 0.04f, UI_CONSTRAINT_RELATIVE); set_y_constraint(&color_slider_con, 0.05f, UI_CONSTRAINT_RELATIVE); set_width_constraint(&color_slider_con, popup_con.width * 0.8f, UI_CONSTRAINT_FIXED); - Vec2f canvas_pos = draw_color_picker_canvas(&color_slider_con, slider_selection, ALIGN_TOP_LEFT); + Color selected_color = draw_color_picker_canvas(&color_slider_con, slider_selection, ALIGN_TOP_LEFT); UIConstraints button_con = default_constraints; set_parent_constraint(&button_con, &popup_con); @@ -774,7 +776,7 @@ void draw_color_picker_popup(UIConstraints *picker_button_con) { set_height_constraint(&button_con, 0.3f, UI_CONSTRAINT_ASPECT_RATIO); UiStyle button_style = { .bg_color = *zephr_ctx->ui.popup_revert_color, - .fg_color = COLOR_BLACK, + .fg_color = determine_color_contrast(zephr_ctx->ui.popup_revert_color), .border_radius = 4, .align = ALIGN_BOTTOM_LEFT, }; @@ -782,9 +784,8 @@ void draw_color_picker_popup(UIConstraints *picker_button_con) { zephr_ctx->ui.popup_open = false; } - Color selected_color = hsv2rgb(slider_selection * 360.f, canvas_pos.x, 1.0f - canvas_pos.y); - button_style.align = ALIGN_BOTTOM_RIGHT; + button_style.fg_color = determine_color_contrast(&selected_color); set_x_constraint(&button_con, -0.04f, UI_CONSTRAINT_RELATIVE); set_y_constraint(&button_con, -0.05f, UI_CONSTRAINT_RELATIVE); button_style.bg_color = selected_color; @@ -796,7 +797,11 @@ void draw_color_picker_popup(UIConstraints *picker_button_con) { zephr_ctx->ui.popup_rect = (Rect){{popup_con.x, popup_con.y}, {popup_con.width, popup_con.height}}; } -void draw_color_picker(UIConstraints *constraints, Color *color, Alignment align, ButtonState state) { +void draw_color_picker_with_location_and_id(u32 id, const char* file, int line, UIConstraints *constraints, Color *color, Alignment align, ButtonState state) { + UiIdHash hash = core_fnv_hash32(&id, sizeof(id), CORE_FNV_HASH32_INIT); + hash = core_fnv_hash32(file, strlen(file), hash); + hash = core_fnv_hash32(&line, sizeof(line), hash); + Rect rect = {0}; Color display_color = *color; @@ -807,6 +812,22 @@ void draw_color_picker(UIConstraints *constraints, Color *color, Alignment align bool is_hovered = inside_rect(&rect, &zephr_ctx->mouse.pos); bool left_mouse_pressed = zephr_ctx->mouse.pressed && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT; + bool left_mouse_released = zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT; + bool clicked = false; + + if (zephr_ctx->ui.active_element == 0) { + if (is_hovered && left_mouse_pressed) { + zephr_ctx->ui.active_element = hash; + } + } else if (zephr_ctx->ui.active_element == hash) { + if (left_mouse_released) { + zephr_ctx->ui.active_element = 0; + + if (is_hovered) { + clicked = true; + } + } + } if (is_hovered && state == BUTTON_STATE_ACTIVE) { zephr_set_cursor(ZEPHR_CURSOR_HAND); @@ -833,7 +854,7 @@ void draw_color_picker(UIConstraints *constraints, Color *color, Alignment align }; draw_quad(&con, style); - if (is_hovered && state == BUTTON_STATE_ACTIVE && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) { + if (clicked && state == BUTTON_STATE_ACTIVE) { zephr_ctx->ui.popup_open = true; zephr_ctx->ui.popup_parent_constraints = con; zephr_ctx->ui.popup_revert_color = color; diff --git a/ui.h b/ui.h index f4605e3..b63d92c 100644 --- a/ui.h +++ b/ui.h @@ -78,7 +78,9 @@ void draw_triangle(UIConstraints *constraints, const UiStyle style); bool draw_button_with_location(const char* file, int line, UIConstraints *constraints, const char *text, UiStyle style, ButtonState state); bool draw_icon_button_with_location(const char* file, int line, UIConstraints *constraints, const TextureId icon_tex_id, UiStyle style, ButtonState state); void draw_color_picker_popup(UIConstraints *picker_button_con); -void draw_color_picker(UIConstraints *constraints, Color *color, Alignment align, ButtonState state); +void draw_color_picker_with_location_and_id(u32 id, const char *file, int line, UIConstraints *constraints, Color *color, Alignment align, ButtonState state); #define draw_button(constraints, text, style, state) draw_button_with_location(__FILE__, __LINE__, constraints, text, style, state) #define draw_icon_button(constraints, icon_tex_id, style, state) draw_icon_button_with_location(__FILE__, __LINE__, constraints, icon_tex_id, style, state) +#define draw_color_picker(constraints, color, align, state) draw_color_picker_with_location_and_id(0, __FILE__, __LINE__, constraints, color, align, state) +#define draw_color_picker_with_id(id, constraints, color, align, state) draw_color_picker_with_location_and_id(id, __FILE__, __LINE__, constraints, color, align, state) diff --git a/zephr.c b/zephr.c index f578cb2..c5a53cb 100644 --- a/zephr.c +++ b/zephr.c @@ -885,9 +885,6 @@ void zephr_quit(void) { zephr_ctx->should_quit = true; } -Color ColorRGBA(u8 r, u8 g, u8 b, u8 a) { - return (Color){ r, g, b, a }; -} ZephrKeyMod zephr_x11_mods_to_zephr_mods(XKeyEvent xkey) { ZephrKeyMod zephr_mods = 0; @@ -1067,9 +1064,10 @@ bool zephr_iter_events(ZephrEvent *event_out) { switch (xev.xbutton.button) { case Button1: event_out->mouse.button = ZEPHR_MOUSE_BUTTON_LEFT; - if (!inside_rect(&zephr_ctx->ui.popup_rect, &event_out->mouse.position)) { - zephr_ctx->ui.popup_open = false; - } + /* if (!inside_rect(&zephr_ctx->ui.popup_rect, &event_out->mouse.position)) { */ + /* zephr_ctx->ui.popup_open = false; */ + /* zephr_ctx->ui.active_element = 0; */ + /* } */ break; case Button2: event_out->mouse.button = ZEPHR_MOUSE_BUTTON_MIDDLE; diff --git a/zephr.h b/zephr.h index 60d09ff..397b703 100644 --- a/zephr.h +++ b/zephr.h @@ -400,7 +400,6 @@ void zephr_swap_buffers(void); Size zephr_get_window_size(void); void zephr_toggle_fullscreen(void); void zephr_quit(void); -Color ColorRGBA(u8 r, u8 g, u8 b, u8 a); bool zephr_iter_events(ZephrEvent *event_out); void zephr_set_cursor(ZephrCursor cursor); diff --git a/zephr_math.c b/zephr_math.c index 1c2c898..7368803 100644 --- a/zephr_math.c +++ b/zephr_math.c @@ -1,5 +1,6 @@ #include +#include "zephr.h" #include "zephr_math.h" float to_radians(float degrees) { @@ -107,3 +108,27 @@ Color hsv2rgb(float h, float s, float v) { return (Color){(u8)((r + m) * 255), (u8)((g + m) * 255), (u8)((b + m) * 255), 255}; } + +f32 get_srgb(u8 c) { + return (f32)(c / 255.f <= 0.03928f + ? c / 255.f / 12.92f + : pow((c / 255.f + 0.055f) / 1.055f, 2.4f)); +} + +f32 get_luminance(Color *color) { + return ((0.2126f * (f32)get_srgb(color->r)) + (0.7152f * (f32)get_srgb(color->g)) + (0.0722f * (f32)get_srgb(color->b))) / 255.f; +} + +f32 get_contrast(Color *fg, Color *bg) { + f32 l1 = get_luminance(fg); + f32 l2 = get_luminance(bg); + + return (CORE_MAX(l1, l2) + 0.05f) / (CORE_MIN(l1, l2) + 0.05f); +} + +Color determine_color_contrast(Color *bg) { + f32 white_contrast = get_contrast(bg, &COLOR_WHITE); + f32 black_contrast = get_contrast(bg, &COLOR_BLACK); + + return white_contrast > black_contrast ? COLOR_WHITE : COLOR_BLACK; +} diff --git a/zephr_math.h b/zephr_math.h index e9d1c0b..a302919 100644 --- a/zephr_math.h +++ b/zephr_math.h @@ -56,3 +56,6 @@ void apply_translation(Matrix4x4 *matrix, Vec2f pos); Matrix4x4 orthographic_projection_2d(float left, float right, float bottom, float top); Color mult_color(Color color, float amount); Color hsv2rgb(float h, float s, float v); +Color determine_color_contrast(Color *bg); + +#define ColorRGBA(r, g, b, a) (Color){r, g, b, a}