From 080f2f1aa4042769ed3c3af0781e7cefb47a0eba Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Mon, 8 Jan 2024 22:27:54 +0200 Subject: [PATCH] zephr/ui: replace styling ui through function arguments with a generic UiStyle struct --- assets/icons/close.png | Bin 630 -> 581 bytes assets/icons/help.png | Bin 2781 -> 2469 bytes assets/icons/settings.png | Bin 1867 -> 1302 bytes game.c | 148 +++++++++++++++++++++++++++++++------- ui.c | 148 ++++++++++++++++++++++---------------- ui.h | 27 ++++--- 6 files changed, 229 insertions(+), 94 deletions(-) diff --git a/assets/icons/close.png b/assets/icons/close.png index 2c5eb06927c2c2ceed81d831bda29e37028c3397..84ee0f774905ece80104238166ef26d96387b465 100644 GIT binary patch delta 556 zcmV+{0@MBW1jPi9B!3J^L_t(|UhSIEZNo4OMB@qCZqQLOLb^dZS+hYqLRRSn%?2(7 z*nnXqGAZ5Bh{Svq2us7fVr8tY|qe%%`+B z(eh@=UjpDJ1zuJ~+#%dCpCtVXfOj^4)N=C(ENi(zcwjzhNh4qyNplCJDj5NE2x3S3j*6b6aX56hj};v6a+8x6acjlJk8Sp zltS<}PX%Cwuz!bnIsh$%z0A7+*n%)UP0i2q?hjX0KZTcSxBkwo^1Vyx4^?wfHvk)* z;J)&^08l`1TloMm5r`4k+PqNTcfASb?(@yx1~or&G%=`7T<4+g0TyGHSR@P@fD%I` z*VMwG0H`rib8QI>H~@qJL=G(sC;+5zWUd?x7yyP~Mt@GqU4SW+nH%yxfGu$AeM0TO z=Bq})!~EQ`tXjnYSb}mJ7Ncen0EQ6lZ3|u73_t|*eLzA0tj`Fg#dCj?^Pm%UIV0q5 zKC>~poDn*TfcYHG*?J~NJL}rGX(TUG{E2={PAlwL;>?@ivl!Fr3;-lP{m2Snm#~c@j>W&hh48SgWw2R*K7fAu(ulUB1=F>WI!3&_Z zoNh}X6@(%2t|ZNdT9RZ3Gz(o!K%gAZYX<>H1pzI-(Gd(l8Uly-XaG_WxWq#Ma6{k} z4+Fpjfm=Kj0Dl^Sgm^dr6a*>pEC6C5NQ!3z5DGzBJSzYygcRc00r)~lC0+!;H3%+= z{*~5Uv7~O8QAc5ys^4>ImxpFci5GJ~C(;LkqG-+u;u4mmz!{64nyQLGN22&0Up%YVE)gAG84ppZGSFjxS@2#J{+ z0s{^JApjA>7X}mnGI3yyAeV?HD@W;s7+!sm1#RGz0)&Ab1h100000NkvXXu0mjfC#(jt diff --git a/assets/icons/help.png b/assets/icons/help.png index d69be42c0cedcad7191ae5d76b5ad7a278d2d91d..d8911ffb5d05f93502dcafebc151ec58cfe2b01f 100644 GIT binary patch delta 2460 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 diff --git a/assets/icons/settings.png b/assets/icons/settings.png index 13b645e45e99b7dd3074c5603b64f38f640d9864..997741a191cf4dd9f54041cdd3dd04860c418cdd 100644 GIT binary patch literal 1302 zcmV+x1?l>UP)Z0A~T1k=qb$Nwz&TB>Vn|MgN|=^6*)1 z0YNVz_LnSMQ+!{O0z$&yS>+H1@a%`L@FL1TWz5P!ng;*{h~fo6im`_!T*q9fX#ix# z8>3G-H_8&41wht&VwK;WPuHYc1|WsK*aepbat~K@!JOPA0Nk|n6Qta{{Gqlo*qUNwjmEh_U61dJ?hJU8;yUUYq1o z$JbwqSh7n+#_@9jJiz_PTBDAXu60V7nvxGJmRERBOPI799F0OEGGa}}(D8MbqjPns z$dEJ^fEs!pU$8g}$gLDIqh%rdfa?*K+`wZJ8{%4K<=XMZt4q{27t*f z=K`4QQU&;XTwE)#_2o;yK+4wZ-j-5IXc!jfuLKBD{Eb#_)@DmF77&>nRnesqI3)pK z$^%t(sfqy*5tCQdr78&k6NOaQr78))4qv9ZE>-Fp*VKYPS&ASRqH4NSOV+r?AZP%X zrxL5^QduQ^8h|axRo|t`RpT160<{`idzUJAjjIoV0Z?t1%Bse741obq?S@$ZFspHO z5L5smCT4bs2R3ykO zC6-wLj%K7R&a3NERRbVc!w#=n#Z+|*n$Jopi_Ctr)VNNvfRswf41f)*7jHB*2_Q@y zrq#OmPVANe6j9@989)&=u4Vz0QsZhJ0J|77F+%?ws>ancfD&q4%>%HmaXEnCIErk_ zGmei;>x;^S$L`BwC$?L_0F9hGu^qsOIpnfz2jBphmFD@JT(dH#EVlr+0Ji{M1H%ym zvs+?T54bOmY^1D8Rtgs+{bB79R;n(d%>;5Q;i_bv3?M96Q?+&K*GV+xcgK|tRjZSg z3V{4Z&mMpM-~7D8d-ANVbe56~0H{h<5&%cDQ`}MayFJp>p7oG4Ln^qV)yql>fKi;E z^HKv2z<5SD00&^K0b}uQ0S>@e1IFUr0vv#`28_kK1vmg>4H%362Nn_vti6(CP5=M^ M07*qoM6N<$g86zrX#fBK literal 1867 zcmV-R2ekN!P)S+6wu2RLi_YH3#b?PxSJ8Z9OM=ac|-D$NTc9;jm_@IXCK#{?XU^BU@b zIws&)oYznf)G-0a;;c1v{n!0X7PCD{X#>VKnnu%;$-n)Ht8qSScMbwdx4FESvEjQx z@5Ght#?N7+UaKE~ycT0@LIe8x`tQ?A8~Ij1pY84+286tt9RMTj7U1sK4y+M|PwJoQ z7vL$k?o5!uOIw|8P5S*?n~5iiz}Pt@^vSH8n2;Cm&Q80gvW4vH7M*H_xow6%Ye;X||1_~2Cf(gGAPKuH(n`OVgyU%36uFp=*#}3P# zFmfT3&&V;nup^TfWE@})mM>phkAt0d6oFP&}3Kc34b4m`d*^Afb}N8tt| z(K1xK8F>TQqD_(Pr35NV^2(Ci2}BQcUYBGEYSef2K<9zVvgX)n!Ln+oG~+Lde3F=- z#urj|3-LuOX+zOv`@hn5NlX*Bi3E%vC!>dR*m>5%0p*)QEvUT$*CjbGFa0rcgr(Nt zWOIV~l)8>R>_~5~&w6){o(n=2256qIRMC=jvt_poz>10!Y_m*du%YNe>eTZ-3jtKg zc8S&L5;E*NWl0OnAJx)OWOvVHJvvZJnCUzO6(4EjQ-`HbzSDwNXe^4X%49w&&}71& zYd4OP7?*IKzEzxLmaQL}+f(*-%7RcO7y9T+9yShsEFs=}G}TJvUuK%x2TlD+MmQq7T-YdDb@ZFIS>95rE{GG2uR{FwW0R$Qu%nBa`YBbY2QMRngR? zg$|If?88#u!?7k-&Wo=Y4 zS#rnTvWQDGaFtsYE`WjzUPr%a3b4$k%A!2!lFx;$?{?rO2mQg>pcJpf*aFo!5zv|% zc0&ZMv3EHztrVN34OI!7`FI$m-GGu2i{l0*L5SrLusc{NQ2zQ{7VZbWV-z0zK%^b z$yeF}#m$u5ZNs!wW=FMv<|?0>01C&s;?0VKqyg!gtY!t-nMv0N_8PG70|DtGvZQVu8|DxQUXPHe}&y#1l0pABjbUpTDY{G*U%DP*txz8 z@j?Q{3c|3fEtpQp4+qtpY|%5Y1T=OKcQ2a~@-e~pP-)S?pvnG!fR70Zuk>K?`n>?< zLQ6k)3F$4!)Nh++>hr;-l`FN&`BMS)s0Ca0EG9g~cjvN%jdt?q8SnD>V6*RVhVTug z22_rWpkl47Td^jac=FO1Nk7O+$67uXJ=vZTc*e2|sWzO5oy1GQP!RqX45 zI)1Ajs0ZqpfMao9Lp@N(1RRU=8tQ>MCg50{*HFhmzW@T;_@EgmLInT-002ovPDHLk FV1hk`h-m-- diff --git a/game.c b/game.c index 4975eda..61775df 100644 --- a/game.c +++ b/game.c @@ -444,7 +444,11 @@ void draw_bg(void) { set_height_constraint(&board_con, window_size.height, UI_CONSTRAINT_FIXED); // bg - draw_quad(&board_con, game.palette.bg_color, 0, ALIGN_TOP_LEFT); + UiStyle style = { + .bg_color = game.palette.bg_color, + .align = ALIGN_TOP_LEFT + }; + draw_quad(&board_con, style); GlyphInstanceList batch; new_glyph_instance_list(&batch, 32); @@ -475,11 +479,20 @@ void draw_quit_dialog(void) { set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED); set_width_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE); - draw_quad(&dialog_con, ColorRGBA(0, 0, 0, 200), 0, ALIGN_CENTER); + UiStyle style = { + .bg_color = ColorRGBA(0, 0, 0, 200), + .align = ALIGN_CENTER, + }; + draw_quad(&dialog_con, style); set_width_constraint(&dialog_con, 0.4f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&dialog_con, 0.2f, UI_CONSTRAINT_RELATIVE); - draw_quad(&dialog_con, ColorRGBA(135, 124, 124, 255), 8, ALIGN_CENTER); + style = (UiStyle){ + .bg_color = ColorRGBA(135, 124, 124, 255), + .border_radius = 8, + .align = ALIGN_CENTER, + }; + draw_quad(&dialog_con, style); UIConstraints text_con = default_constraints; set_parent_constraint(&text_con, &dialog_con); @@ -494,13 +507,19 @@ void draw_quit_dialog(void) { set_height_constraint(&btn_con, 0.25f, UI_CONSTRAINT_RELATIVE); set_y_constraint(&btn_con, -0.10f, UI_CONSTRAINT_RELATIVE); set_x_constraint(&btn_con, -0.20f, UI_CONSTRAINT_RELATIVE); - if (draw_button(&btn_con, mult_color(COLOR_WHITE, 0.9f), "Yes", btn_con.height * 0.20f, ALIGN_BOTTOM_CENTER, BUTTON_STATE_ACTIVE)) { + style = (UiStyle){ + .bg_color = mult_color(COLOR_WHITE, 0.9f), + .fg_color = COLOR_BLACK, + .border_radius = btn_con.height * 0.2f, + .align = ALIGN_BOTTOM_CENTER, + }; + if (draw_button(&btn_con, "Yes", style, BUTTON_STATE_ACTIVE)) { zephr_quit(); } set_y_constraint(&btn_con, -0.10f, UI_CONSTRAINT_RELATIVE); set_x_constraint(&btn_con, 0.20f, UI_CONSTRAINT_RELATIVE); - if (draw_button(&btn_con, mult_color(COLOR_WHITE, 0.9f), "No", btn_con.height * 0.20f, ALIGN_BOTTOM_CENTER, BUTTON_STATE_ACTIVE)) { + if (draw_button(&btn_con, "No", style, BUTTON_STATE_ACTIVE)) { game.quit_dialog = false; } } @@ -511,13 +530,22 @@ void draw_help_dialog(void) { set_height_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE); set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED); set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED); - draw_quad(&dialog_con, ColorRGBA(0, 0, 0, 200), 0, ALIGN_CENTER); + UiStyle style = { + .bg_color = ColorRGBA(0, 0, 0, 200), + .align = ALIGN_CENTER, + }; + draw_quad(&dialog_con, style); UIConstraints content_card_con = default_constraints; set_parent_constraint(&content_card_con, &dialog_con); set_width_constraint(&content_card_con, 0.4f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&content_card_con, 0.33f, UI_CONSTRAINT_RELATIVE); - draw_quad(&content_card_con, ColorRGBA(135, 124, 124, 255), 8, ALIGN_CENTER); + style = (UiStyle){ + .bg_color = ColorRGBA(135, 124, 124, 255), + .border_radius = 8, + .align = ALIGN_CENTER, + }; + draw_quad(&content_card_con, style); UIConstraints text_con = default_constraints; set_parent_constraint(&text_con, &content_card_con); @@ -538,7 +566,13 @@ void draw_help_dialog(void) { set_height_constraint(&btn_con, 1, UI_CONSTRAINT_ASPECT_RATIO); set_y_constraint(&btn_con, -24, UI_CONSTRAINT_RELATIVE_PIXELS); set_x_constraint(&btn_con, 24, UI_CONSTRAINT_RELATIVE_PIXELS); - if (draw_icon_button(&btn_con, mult_color(COLOR_WHITE, 0.8f), game.icon_textures[CLOSE_ICON], btn_con.height * 0.20f, ALIGN_TOP_RIGHT, BUTTON_STATE_ACTIVE)) { + style = (UiStyle){ + .bg_color = mult_color(COLOR_WHITE, 0.8f), + .fg_color = ColorRGBA(232, 28, 36, 255), + .border_radius = btn_con.height * 0.2f, + .align = ALIGN_TOP_RIGHT, + }; + if (draw_icon_button(&btn_con, game.icon_textures[CLOSE_ICON], style, BUTTON_STATE_ACTIVE)) { game.help_dialog = false; } } @@ -549,13 +583,22 @@ void draw_settings_dialog(void) { set_height_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE); set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED); set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED); - draw_quad(&dialog_con, ColorRGBA(0, 0, 0, 200), 0, ALIGN_CENTER); + UiStyle style = { + .bg_color = ColorRGBA(0, 0, 0, 200), + .align = ALIGN_CENTER, + }; + draw_quad(&dialog_con, style); UIConstraints content_card_con = default_constraints; set_parent_constraint(&content_card_con, &dialog_con); set_width_constraint(&content_card_con, 0.55f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&content_card_con, 0.6f, UI_CONSTRAINT_RELATIVE); - draw_quad(&content_card_con, ColorRGBA(135, 124, 124, 255), 8, ALIGN_CENTER); + style = (UiStyle){ + .bg_color = ColorRGBA(135, 124, 124, 255), + .border_radius = 8, + .align = ALIGN_CENTER, + }; + draw_quad(&content_card_con, style); UIConstraints text_con = default_constraints; set_parent_constraint(&text_con, &content_card_con); @@ -621,7 +664,13 @@ void draw_settings_dialog(void) { set_y_constraint(&btn_con, 400, UI_CONSTRAINT_RELATIVE_PIXELS); set_width_constraint(&btn_con, 150, UI_CONSTRAINT_RELATIVE_PIXELS); set_height_constraint(&btn_con, 0.35f, UI_CONSTRAINT_ASPECT_RATIO); - if (draw_button(&btn_con, ColorRGBA(201, 146, 126, 255), "Reset", 8.f, ALIGN_TOP_CENTER, BUTTON_STATE_ACTIVE)) { + style = (UiStyle){ + .bg_color = ColorRGBA(201, 146, 126, 255), + .fg_color = COLOR_BLACK, + .border_radius = 8, + .align = ALIGN_TOP_CENTER, + }; + if (draw_button(&btn_con, "Reset", style, BUTTON_STATE_ACTIVE)) { reset_palette(); } @@ -629,7 +678,13 @@ void draw_settings_dialog(void) { set_height_constraint(&btn_con, 1, UI_CONSTRAINT_ASPECT_RATIO); set_y_constraint(&btn_con, -24, UI_CONSTRAINT_RELATIVE_PIXELS); set_x_constraint(&btn_con, 24, UI_CONSTRAINT_RELATIVE_PIXELS); - if (draw_icon_button(&btn_con, mult_color(COLOR_WHITE, 0.8f), game.icon_textures[CLOSE_ICON], btn_con.height * 0.20f, ALIGN_TOP_RIGHT, BUTTON_STATE_ACTIVE)) { + style = (UiStyle){ + .bg_color = mult_color(COLOR_WHITE, 0.8f), + .fg_color = ColorRGBA(232, 28, 36, 255), + .border_radius = btn_con.height * 0.2f, + .align = ALIGN_TOP_RIGHT, + }; + if (draw_icon_button(&btn_con, game.icon_textures[CLOSE_ICON], style, BUTTON_STATE_ACTIVE)) { game.settings_dialog = false; } } @@ -640,13 +695,22 @@ void draw_game_over(void) { set_height_constraint(&dialog_con, 1.f, UI_CONSTRAINT_RELATIVE); set_x_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED); set_y_constraint(&dialog_con, 0, UI_CONSTRAINT_FIXED); - draw_quad(&dialog_con, ColorRGBA(0, 0, 0, (u8)game.game_over_bg_opacity), 0, ALIGN_CENTER); + UiStyle style = { + .bg_color = ColorRGBA(0, 0, 0, (u8)game.game_over_bg_opacity), + .align = ALIGN_CENTER, + }; + draw_quad(&dialog_con, style); UIConstraints content_card_con = default_constraints; set_parent_constraint(&content_card_con, &dialog_con); set_width_constraint(&content_card_con, 0.3f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&content_card_con, 0.2f, UI_CONSTRAINT_RELATIVE); - draw_quad(&content_card_con, ColorRGBA(135, 124, 124, (u8)game.game_over_opacity), 8, ALIGN_CENTER); + style = (UiStyle){ + .bg_color = ColorRGBA(135, 124, 124, (u8)game.game_over_opacity), + .border_radius = 8, + .align = ALIGN_CENTER, + }; + draw_quad(&content_card_con, style); UIConstraints text_con = default_constraints; set_parent_constraint(&text_con, &content_card_con); @@ -662,7 +726,12 @@ void draw_game_over(void) { set_y_constraint(&btn_con, -24, UI_CONSTRAINT_RELATIVE_PIXELS); set_width_constraint(&btn_con, 0.30f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&btn_con, 0.3f, UI_CONSTRAINT_ASPECT_RATIO); - if (draw_button(&btn_con, ColorRGBA(201, 146, 126, (u8)game.game_over_opacity), "Try Again", 8.f, ALIGN_BOTTOM_CENTER, btn_state)) { + style = (UiStyle){ + .bg_color = ColorRGBA(201, 146, 126, (u8)game.game_over_opacity), + .border_radius = 8, + .align = ALIGN_BOTTOM_CENTER, + }; + if (draw_button(&btn_con, "Try Again", style, btn_state)) { reset_game(); } } @@ -681,12 +750,18 @@ void draw_ui(void) { set_width_constraint(&btn_con, icon_btn_width, UI_CONSTRAINT_RELATIVE_PIXELS); set_height_constraint(&btn_con, 1, UI_CONSTRAINT_ASPECT_RATIO); - if (draw_icon_button(&btn_con, ColorRGBA(201, 146, 126, 255), game.icon_textures[HELP_ICON], btn_con.height * 0.15f, ALIGN_TOP_RIGHT, bg_btns_state)) { + UiStyle style = { + .bg_color = ColorRGBA(201, 146, 126, 255), + .fg_color = ColorRGBA(40, 92, 100, 255), + .border_radius = btn_con.height * 0.15f, + .align = ALIGN_TOP_RIGHT, + }; + if (draw_icon_button(&btn_con, game.icon_textures[HELP_ICON], style, bg_btns_state)) { game.help_dialog = true; } set_x_constraint(&btn_con, -icon_btn_offset - icon_btn_width - icon_btns_padding, UI_CONSTRAINT_RELATIVE_PIXELS); - if (draw_icon_button(&btn_con, ColorRGBA(201, 146, 126, 255), game.icon_textures[SETTINGS_ICON], btn_con.height * 0.15f, ALIGN_TOP_RIGHT, bg_btns_state)) { + if (draw_icon_button(&btn_con, game.icon_textures[SETTINGS_ICON], style, bg_btns_state)) { game.settings_dialog = true; } @@ -694,7 +769,13 @@ void draw_ui(void) { set_y_constraint(&btn_con, -0.05f, UI_CONSTRAINT_RELATIVE); set_width_constraint(&btn_con, 200, UI_CONSTRAINT_RELATIVE_PIXELS); set_height_constraint(&btn_con, 65, UI_CONSTRAINT_RELATIVE_PIXELS); - if (draw_button(&btn_con, ColorRGBA(201, 172, 126, 255), "New Game", btn_con.height * 0.25f, ALIGN_BOTTOM_CENTER, bg_btns_state)) { + style = (UiStyle) { + .bg_color = ColorRGBA(201, 172, 126, 255), + .fg_color = COLOR_BLACK, + .border_radius = btn_con.height * 0.25f, + .align = ALIGN_BOTTOM_CENTER, + }; + if (draw_button(&btn_con, "New Game", style, bg_btns_state)) { reset_game(); } @@ -721,8 +802,12 @@ void draw_board(void) { set_y_constraint(&board_con, 0.05f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&board_con, 0.6f, UI_CONSTRAINT_RELATIVE); set_width_constraint(&board_con, 1, UI_CONSTRAINT_ASPECT_RATIO); - const float board_border_radius = board_con.width * 0.02f; - draw_quad(&board_con, game.palette.board_bg_color, board_border_radius, ALIGN_CENTER); + UiStyle style = { + .bg_color = game.palette.board_bg_color, + .border_radius = board_con.width * 0.02f, + .align = ALIGN_CENTER, + }; + draw_quad(&board_con, style); // empty tiles const float tile_padding = board_con.width * 0.02f; @@ -734,11 +819,16 @@ void draw_board(void) { set_height_constraint(&empty_tile_con, tile_height, UI_CONSTRAINT_FIXED); set_width_constraint(&empty_tile_con, 1, UI_CONSTRAINT_ASPECT_RATIO); + style = (UiStyle){ + .bg_color = mult_color(game.palette.board_bg_color, 0.85f), + .border_radius = tile_board_radius, + .align = ALIGN_TOP_LEFT, + }; for (int i = 0; i < 4; i++) { set_y_constraint(&empty_tile_con, (tile_height + tile_padding) * i + tile_padding, UI_CONSTRAINT_FIXED); for (int j = 0; j < 4; j++) { set_x_constraint(&empty_tile_con, (tile_height + tile_padding) * j + tile_padding, UI_CONSTRAINT_FIXED); - draw_quad(&empty_tile_con, mult_color(game.palette.board_bg_color, 0.85f), tile_board_radius, ALIGN_TOP_LEFT); + draw_quad(&empty_tile_con, style); } } @@ -754,6 +844,11 @@ void draw_board(void) { for (int j = 0; j < 4; j++) { Tile *tile = &game.board[i][j]; Color tile_color = get_tile_color(tile->value); + UiStyle style = { + .bg_color = tile_color, + .border_radius = tile_board_radius, + .align = ALIGN_TOP_LEFT, + }; char value[16]; sprintf(value, "%d", tile->value); f32 tile_y_pos = (f32)((tile_height + tile_padding) * i + tile_padding + game.board[i][j].anim_y_offset_relative * board_con.height); @@ -762,7 +857,7 @@ void draw_board(void) { set_y_constraint(&tile_con, tile_y_pos, UI_CONSTRAINT_FIXED); set_x_constraint(&tile_con, tile_x_pos, UI_CONSTRAINT_FIXED); if (tile->value > 0) { - draw_quad(&tile_con, tile_color, tile_board_radius, ALIGN_TOP_LEFT); + draw_quad(&tile_con, style); // value text set_parent_constraint(&text_con, &tile_con); @@ -777,13 +872,18 @@ void draw_board(void) { if (game.spawning_new_tile) { // spawning tile Color tile_color = get_tile_color(game.spawning_tile_value); + UiStyle style = { + .bg_color = tile_color, + .border_radius = tile_board_radius, + .align = ALIGN_TOP_LEFT, + }; f32 tile_x_pos = (f32)((tile_height + tile_padding) * game.spawning_tile_coords.y + tile_padding) + tile_height / 2 - game.spawning_tile_scale * tile_height / 2; f32 tile_y_pos = (f32)((tile_height + tile_padding) * game.spawning_tile_coords.x + tile_padding) + tile_height / 2 - game.spawning_tile_scale * tile_height / 2; set_x_constraint(&tile_con, tile_x_pos, UI_CONSTRAINT_FIXED); set_y_constraint(&tile_con, tile_y_pos, UI_CONSTRAINT_FIXED); set_height_constraint(&tile_con, tile_height * game.spawning_tile_scale, UI_CONSTRAINT_FIXED); set_width_constraint(&tile_con, 1, UI_CONSTRAINT_ASPECT_RATIO); - draw_quad(&tile_con, tile_color, tile_board_radius, ALIGN_TOP_LEFT); + draw_quad(&tile_con, style); // value text set_parent_constraint(&text_con, &tile_con); set_x_constraint(&text_con, 0, UI_CONSTRAINT_FIXED); @@ -944,7 +1044,7 @@ void update_positions(f64 delta_t) { void handle_keyboard_input(ZephrEvent e) { - bool can_move = !game.quit_dialog && !game.help_dialog && !game.animating; + bool can_move = !game.quit_dialog && !game.help_dialog && !game.settings_dialog && !game.animating; if (e.key.mods & ZEPHR_KEY_MOD_CTRL && e.key.code == ZEPHR_KEYCODE_Q) { game_attempt_quit(); diff --git a/ui.c b/ui.c index b28c31a..cd86d0c 100644 --- a/ui.c +++ b/ui.c @@ -216,35 +216,34 @@ bool inside_rect(Rect *rect, Vec2 *point) { return false; } -void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align) { +void draw_quad(UIConstraints *constraints, const UiStyle style) { use_shader(ui_shader); - set_vec4f(ui_shader, "aColor", color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); + set_vec4f(ui_shader, "aColor", style.bg_color.r / 255.f, style.bg_color.g / 255.f, style.bg_color.b / 255.f, style.bg_color.a / 255.f); set_float(ui_shader, "uiWidth", constraints->width); set_float(ui_shader, "uiHeight", constraints->height); - set_float(ui_shader, "borderRadius", border_radius); + set_float(ui_shader, "borderRadius", style.border_radius); set_mat4f(ui_shader, "projection", (float *)zephr_ctx->projection.m); - Vec2f pos = { 0.f, 0.f }; - Sizef size = { 0.f, 0.f }; + Rect rect = {0}; - apply_constraints(constraints, &pos, &size); - apply_alignment(align, constraints, &pos, size); + apply_constraints(constraints, &rect.pos, &rect.size); + apply_alignment(style.align, constraints, &rect.pos, rect.size); // set the positions after applying alignment so children can use them - constraints->x = pos.x; - constraints->y = pos.y; + constraints->x = rect.pos.x; + constraints->y = rect.pos.y; Matrix4x4 model = identity(); - apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f}); + apply_translation(&model, (Vec2f){-rect.size.width / 2.f, -rect.size.height / 2.f}); apply_scale(&model, constraints->scale); - apply_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f}); + apply_translation(&model, (Vec2f){rect.size.width / 2.f, rect.size.height / 2.f}); - apply_translation(&model, (Vec2f){-size.width / 2.f, -size.height / 2.f}); + apply_translation(&model, (Vec2f){-rect.size.width / 2.f, -rect.size.height / 2.f}); apply_rotation(&model, to_radians(constraints->rotation)); - apply_translation(&model, (Vec2f){size.width / 2.f, size.height / 2.f}); + apply_translation(&model, (Vec2f){rect.size.width / 2.f, rect.size.height / 2.f}); - apply_translation(&model, pos); + apply_translation(&model, rect.pos); set_mat4f(ui_shader, "model", (float *)model.m); @@ -252,14 +251,14 @@ void draw_quad(UIConstraints *constraints, const Color color, float border_radiu float vertices[6][4] = { // bottom left tri - {0, 0 + size.height, 0.0, 1.0}, - {0, 0, 0.0, 0.0}, - {0 + size.width, 0, 1.0, 0.0}, + {0, 0 + rect.size.height, 0.0, 1.0}, + {0, 0, 0.0, 0.0}, + {0 + rect.size.width, 0, 1.0, 0.0}, // top right tri - {0, 0 + size.height, 0.0, 1.0}, - {0 + size.width, 0, 1.0, 0.0}, - {0 + size.width, 0 + size.height, 1.0, 1.0}, + {0, 0 + rect.size.height, 0.0, 1.0}, + {0 + rect.size.width, 0, 1.0, 0.0}, + {0 + rect.size.width, 0 + rect.size.height, 1.0, 1.0}, }; glBindBuffer(GL_ARRAY_BUFFER, ui_vbo); @@ -271,7 +270,7 @@ void draw_quad(UIConstraints *constraints, const Color color, float border_radiu glBindVertexArray(0); } -void draw_circle(UIConstraints *constraints, const Color color, Alignment align) { +void draw_circle(UIConstraints *constraints, const UiStyle style) { float radius = 0.f; if (constraints->width > constraints->height) { @@ -279,13 +278,17 @@ void draw_circle(UIConstraints *constraints, const Color color, Alignment align) } else { radius = constraints->width / 2.f; } - draw_quad(constraints, color, radius, align); + + UiStyle new_style = style; + new_style.border_radius = radius; + + draw_quad(constraints, new_style); } -void draw_triangle(UIConstraints *constraints, const Color color, Alignment align) { +void draw_triangle(UIConstraints *constraints, const UiStyle style) { use_shader(ui_shader); - set_vec4f(ui_shader, "aColor", color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); + set_vec4f(ui_shader, "aColor", style.bg_color.r / 255.f, style.bg_color.g / 255.f, style.bg_color.b / 255.f, style.bg_color.a / 255.f); set_float(ui_shader, "borderRadius", 0.f); set_mat4f(ui_shader, "projection", (float *)zephr_ctx->projection.m); @@ -293,7 +296,7 @@ void draw_triangle(UIConstraints *constraints, const Color color, Alignment alig Sizef size = { 0.f, 0.f }; apply_constraints(constraints, &pos, &size); - apply_alignment(align, constraints, &pos, size); + apply_alignment(style.align, constraints, &pos, size); // set the positions after applying alignment so children can use them constraints->x = pos.x; @@ -390,16 +393,15 @@ void draw_texture(UIConstraints *constraints, const TextureId texture_id, const set_bool(ui_shader, "hasTexture", false); } -bool draw_button_with_location(const char *file, int line, UIConstraints *constraints, const Color color, const char *text, f32 radius, Alignment align, ButtonState state) { +bool draw_button_with_location(const char *file, int line, UIConstraints *constraints, const char *text, UiStyle style, ButtonState state) { UiIdHash hash = core_fnv_hash32(file, strlen(file), CORE_FNV_HASH32_INIT); hash = core_fnv_hash32(&line, sizeof(line), hash); - Color text_color = COLOR_BLACK; - text_color.a = color.a; + style.fg_color.a = style.bg_color.a; Rect rect = {0}; apply_constraints(constraints, &rect.pos, &rect.size); - apply_alignment(align, constraints, &rect.pos, rect.size); + apply_alignment(style.align, constraints, &rect.pos, rect.size); 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; @@ -424,23 +426,22 @@ bool draw_button_with_location(const char *file, int line, UIConstraints *constr zephr_set_cursor(ZEPHR_CURSOR_HAND); if (left_mouse_pressed) { - Color new_color = mult_color(color, 0.8f); - draw_quad(constraints, new_color, radius, align); + style.bg_color = mult_color(style.bg_color, 0.8f); + draw_quad(constraints, style); } else { - Color new_color = mult_color(color, 0.9f); - draw_quad(constraints, new_color, radius, align); + style.bg_color = mult_color(style.bg_color, 0.9f); + draw_quad(constraints, style); } } else if (state == BUTTON_STATE_DISABLED) { if (is_hovered) { zephr_set_cursor(ZEPHR_CURSOR_DISABLED); } - Color new_color = color; - new_color.a = 100; - text_color.a = 100; - draw_quad(constraints, new_color, radius, align); + style.bg_color.a = 100; + style.fg_color.a = 100; + draw_quad(constraints, style); } else { - draw_quad(constraints, color, radius, align); + draw_quad(constraints, style); } if (text) { @@ -455,7 +456,7 @@ bool draw_button_with_location(const char *file, int line, UIConstraints *constr // TODO: need to adjust the font size based on the text height - draw_text(text, font_size, text_constraints, text_color, ALIGN_CENTER); + draw_text(text, font_size, text_constraints, style.fg_color, ALIGN_CENTER); } if (clicked && state == BUTTON_STATE_ACTIVE) { @@ -465,17 +466,16 @@ bool draw_button_with_location(const char *file, int line, UIConstraints *constr return false; } -bool draw_icon_button_with_location(const char *file, int line, UIConstraints *constraints, Color btn_color, const TextureId icon_tex_id, f32 radius, Alignment align, ButtonState state) { +bool draw_icon_button_with_location(const char *file, int line, UIConstraints *constraints, const TextureId icon_tex_id, UiStyle style, ButtonState state) { CORE_DEBUG_ASSERT(icon_tex_id, "draw_icon_button() requires that you provide an icon texture"); UiIdHash hash = core_fnv_hash32(file, strlen(file), CORE_FNV_HASH32_INIT); hash = core_fnv_hash32(&line, sizeof(line), hash); Rect rect = {0}; - Color icon_color = COLOR_WHITE; apply_constraints(constraints, &rect.pos, &rect.size); - apply_alignment(align, constraints, &rect.pos, rect.size); + apply_alignment(style.align, constraints, &rect.pos, rect.size); 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; @@ -500,22 +500,22 @@ bool draw_icon_button_with_location(const char *file, int line, UIConstraints *c zephr_set_cursor(ZEPHR_CURSOR_HAND); if (left_mouse_pressed) { - btn_color = mult_color(btn_color, 0.8f); - icon_color = mult_color(icon_color, 0.8f); + style.bg_color = mult_color(style.bg_color, 0.8f); + style.fg_color = mult_color(style.fg_color, 0.8f); } else { - btn_color = mult_color(btn_color, 0.9f); - icon_color = mult_color(icon_color, 0.9f); + style.bg_color = mult_color(style.bg_color, 0.9f); + style.fg_color = mult_color(style.fg_color, 0.9f); } } else if (state == BUTTON_STATE_DISABLED) { if (is_hovered) { zephr_set_cursor(ZEPHR_CURSOR_DISABLED); } - icon_color.a = 100; - btn_color.a = 100; + style.fg_color.a = 100; + style.bg_color.a = 100; } - draw_quad(constraints, btn_color, radius, align); + draw_quad(constraints, style); UIConstraints icon_constraints = default_constraints; @@ -524,7 +524,7 @@ bool draw_icon_button_with_location(const char *file, int line, UIConstraints *c set_y_constraint(&icon_constraints, 0, UI_CONSTRAINT_RELATIVE_PIXELS); set_width_constraint(&icon_constraints, constraints->width * 0.8f, UI_CONSTRAINT_FIXED); set_height_constraint(&icon_constraints, constraints->height * 0.8f, UI_CONSTRAINT_FIXED); - draw_texture(&icon_constraints, icon_tex_id, icon_color, 0, ALIGN_CENTER); + draw_texture(&icon_constraints, icon_tex_id, style.fg_color, 0, ALIGN_CENTER); if (clicked && state == BUTTON_STATE_ACTIVE) { return true; @@ -613,12 +613,17 @@ f32 draw_color_picker_slider_with_location(const char *file, int line, UIConstra set_width_constraint(&triangle_con, 14, UI_CONSTRAINT_RELATIVE_PIXELS); set_height_constraint(&triangle_con, 0.5f, UI_CONSTRAINT_ASPECT_RATIO); triangle_con.y += -(triangle_con.height / 2.f); - draw_triangle(&triangle_con, COLOR_BLACK, ALIGN_TOP_LEFT); + UiStyle tri_style = { + .bg_color = COLOR_BLACK, + .border_radius = 0, + .align = ALIGN_TOP_LEFT, + }; + draw_triangle(&triangle_con, tri_style); set_x_constraint(&triangle_con, 1, UI_CONSTRAINT_RELATIVE); triangle_con.x -= triangle_con.height / 2; set_rotation_constraint(&triangle_con, 90); - draw_triangle(&triangle_con, COLOR_BLACK, ALIGN_TOP_LEFT); + draw_triangle(&triangle_con, tri_style); return slider_selection; } @@ -708,22 +713,27 @@ Vec2f draw_color_picker_canvas_with_location(const char* file, int line, UIConst triangle_con.x -= triangle_con.height; triangle_con.y -= triangle_con.height * 2; set_rotation_constraint(&triangle_con, 0); - draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT); + UiStyle tri_style = { + .bg_color = COLOR_WHITE, + .border_radius = 0, + .align = ALIGN_TOP_LEFT, + }; + draw_triangle(&triangle_con, tri_style); triangle_con.x += triangle_con.height * 2; triangle_con.y += triangle_con.height * 2; set_rotation_constraint(&triangle_con, 90); - draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT); + draw_triangle(&triangle_con, tri_style); triangle_con.x -= triangle_con.height * 2; triangle_con.y += triangle_con.height * 2; set_rotation_constraint(&triangle_con, 180); - draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT); + draw_triangle(&triangle_con, tri_style); triangle_con.x -= triangle_con.height * 2; triangle_con.y -= triangle_con.height * 2; set_rotation_constraint(&triangle_con, 270); - draw_triangle(&triangle_con, COLOR_WHITE, ALIGN_TOP_LEFT); + draw_triangle(&triangle_con, tri_style); return canvas_pos; } @@ -736,7 +746,12 @@ void draw_color_picker_popup(UIConstraints *picker_button_con) { set_y_constraint(&popup_con, picker_button_con->height + 20, UI_CONSTRAINT_FIXED); set_width_constraint(&popup_con, 450, UI_CONSTRAINT_RELATIVE_PIXELS); set_height_constraint(&popup_con, 480, UI_CONSTRAINT_RELATIVE_PIXELS); - draw_quad(&popup_con, mult_color(COLOR_WHITE, 0.94f), 8, ALIGN_TOP_LEFT); + UiStyle popup_style = { + .bg_color = mult_color(COLOR_WHITE, 0.94f), + .border_radius = 8, + .align = ALIGN_TOP_LEFT, + }; + draw_quad(&popup_con, popup_style); UIConstraints color_slider_con = default_constraints; set_parent_constraint(&color_slider_con, &popup_con); @@ -757,15 +772,23 @@ void draw_color_picker_popup(UIConstraints *picker_button_con) { set_y_constraint(&button_con, -0.05f, UI_CONSTRAINT_RELATIVE); set_width_constraint(&button_con, 0.43f, UI_CONSTRAINT_RELATIVE); set_height_constraint(&button_con, 0.3f, UI_CONSTRAINT_ASPECT_RATIO); - if (draw_button(&button_con, *zephr_ctx->ui.popup_revert_color, "Revert", 4, ALIGN_BOTTOM_LEFT, BUTTON_STATE_ACTIVE)) { + UiStyle button_style = { + .bg_color = *zephr_ctx->ui.popup_revert_color, + .fg_color = COLOR_BLACK, + .border_radius = 4, + .align = ALIGN_BOTTOM_LEFT, + }; + if (draw_button(&button_con, "Revert", button_style, BUTTON_STATE_ACTIVE)) { 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; set_x_constraint(&button_con, -0.04f, UI_CONSTRAINT_RELATIVE); set_y_constraint(&button_con, -0.05f, UI_CONSTRAINT_RELATIVE); - if (draw_button(&button_con, selected_color, "Apply", 4, ALIGN_BOTTOM_RIGHT, BUTTON_STATE_ACTIVE)) { + button_style.bg_color = selected_color; + if (draw_button(&button_con, "Apply", button_style, BUTTON_STATE_ACTIVE)) { *zephr_ctx->ui.popup_revert_color = selected_color; zephr_ctx->ui.popup_open = false; } @@ -803,7 +826,12 @@ void draw_color_picker(UIConstraints *constraints, Color *color, Alignment align display_color.a = 100; } - draw_quad(&con, display_color, con.width * 0.08f, align); + UiStyle style = { + .bg_color = display_color, + .border_radius = con.width * 0.08f, + .align = align, + }; + draw_quad(&con, style); if (is_hovered && state == BUTTON_STATE_ACTIVE && zephr_ctx->mouse.released && zephr_ctx->mouse.button == ZEPHR_MOUSE_BUTTON_LEFT) { zephr_ctx->ui.popup_open = true; diff --git a/ui.h b/ui.h index 711f35e..f4605e3 100644 --- a/ui.h +++ b/ui.h @@ -55,6 +55,13 @@ typedef enum ButtonState { BUTTON_STATE_DISABLED, } ButtonState; +typedef struct UiStyle { + Color bg_color; + Color fg_color; + f32 border_radius; + Alignment align; +} UiStyle; + int init_ui(const char* font_path); void set_parent_constraint(UIConstraints *constraints, UIConstraints *parent_constraints); void set_x_constraint(UIConstraints *constraints, float value, UIConstraint type); @@ -62,16 +69,16 @@ void set_y_constraint(UIConstraints *constraints, float value, UIConstraint type void set_width_constraint(UIConstraints *constraints, float value, UIConstraint type); void set_height_constraint(UIConstraints *constraints, float value, UIConstraint type); void set_rotation_constraint(UIConstraints *constraints, float angle_d); -void apply_constraints(UIConstraints *constraints, Vec2f *pos, Sizef *size); -void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Sizef size); -bool inside_rect(Rect *rect, Vec2 *point); -void draw_quad(UIConstraints *constraints, const Color color, float border_radius, Alignment align); -void draw_circle(UIConstraints *constraints, const Color color, Alignment align); -void draw_triangle(UIConstraints *constraints, const Color color, Alignment align); -bool draw_button_with_location(const char* file, int line, UIConstraints *constraints, Color color, const char *text, f32 radius, Alignment align, ButtonState state); -bool draw_icon_button_with_location(const char* fie, int line, UIConstraints *constraints, Color color, const TextureId icon_tex_id, f32 radius, Alignment align, ButtonState state); +void apply_constraints(UIConstraints *constraints, Vec2f *pos, Sizef *size); // internal +void apply_alignment(Alignment align, UIConstraints *constraints, Vec2f *pos, Sizef size); // internal +bool inside_rect(Rect *rect, Vec2 *point); // internal +void draw_quad(UIConstraints *constraints, const UiStyle style); +void draw_circle(UIConstraints *constraints, const UiStyle style); +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); -#define draw_button(constraints, color, text, radius, align, state) draw_button_with_location(__FILE__, __LINE__, constraints, color, text, radius, align, state) -#define draw_icon_button(constraints, color, icon_tex_id, radius, align, state) draw_icon_button_with_location(__FILE__, __LINE__, constraints, color, icon_tex_id, radius, align, 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)