From 79f735e7b5af3d3f4dc026bc5d1fe6c196ed0006 Mon Sep 17 00:00:00 2001 From: Emil Kosz Date: Mon, 16 Jun 2025 13:43:35 +0200 Subject: [PATCH] IDK --- game/res/textures/font_9x20.png | Bin 2545 -> 2562 bytes game/res/textures/font_9x20.xcf | Bin 26422 -> 26493 bytes game/src/ui/uiman.c | 12 ++- game/src/ui/widget_layout.c | 176 +++++++++++++++++--------------- 4 files changed, 100 insertions(+), 88 deletions(-) diff --git a/game/res/textures/font_9x20.png b/game/res/textures/font_9x20.png index df17ae699e32fcf787276a9546d5a717c5d105bc..7a60e0e62f8fa3d98016fcbf671e086e2cd526dc 100644 GIT binary patch delta 2390 zcmew;+$1s~SFgd-#WAGf*4w)mCoNea#Bf1#@xTAmzwf&zR#IHbKSZy z7nUO;|NbyeZsZiN{~`PDr@duieDqh(yZ_(4cz*tT)a~2#>XZ8JrB6I0p}A&l?%8+A z|KA7ezgb&#Saha{X2AOEuT5{cf7$F2m7aC@UU~fb>#vLB?T>$4a%l3pMz^g_sZ939 zW$_VJGw=U;bNuF(_uEZ>{n>7I-~RZ{wKpmPK%cq9S`?C3WSI@rwZH1@Ra?)BV<0GPy9n;-A)Bo)&a{0CH`D4Sk>z9Ab z{_OTotKMe8H3o)?E4p>7lg*@9ZKWGbf1Rr<+4*%r;gokT-uJV~RU5i4UjBda(;8TGcTU>I8gJ&dg9--dDqgD<|*G^=~etpZ*`W7Rq>nK`%*$%SZEdPksQdl5wd$WZlD-+bsy)yNI=t;u#r*TP>n|R2lN4CX=YH08^~)0} z2YjlkT6HErd-eF#6&X?f9m-o@?f+LN5_IcS$ITC?JQn7#u1QT=yV?K9=HK&Qdb|FT zG5$O0X2FBN|GK;0Uw{4e*12!h=eDf9sr_OFTgMyiY8m&1YJ0hrgk+|#ja;2IFQ<5$ z{lDuMWqtKaN}s*zH|sRcuMcopENrY^Xm()#_r0MH_iJ;V&pCUoMtkui+ody^|J=Nv zerVD5b8DNeSN&6N%~G57adzX+iRRIp^Ha}=&8xrLI`?eLnX87<=WTY+z1jEnRbTzl z+&^!u^R=_Lm9M|H^2N>YlAQ3|^rs4O?>EP(TmHINvtI4gJ&TloW!AS&tkTvNs$UmX zDzy5W=*@GY+uy9tT9olHb1U2XHytVOQ??w7G%7E17uI_7+i$gd*6LaF|8g@dp0#w9 ze@NixlHU&D`<_*QF+0|E@%^dCT}vv>`gU)sw3}TYSNhAN} zf&P8sopEz^UX|rN=DJOMZj-*z2k~BIDOdG+m-!#gFR}b}VT<*I8J*sJZtGK%+rRIR zw_W=oXV$rQ#>Ty8XC|MPd#=&;_wH&=qlJRTh1>Slx^6QLp6t@E9b8dmdTb_B<#NZP z*DCM#IT^0LXV7tk@Bbg0Dm#(8@kg_DMf=069;#0CJh__bxYo3a7q&0&hfVuo&38JT z+x_Uqlx6iVZLOCFh6>;Kb+>w(@GQ-LIm@&sJ#ZY`cDcRh-Y$RnP2y8Kq=0uJZX4``gKXh3vX> z+t2*l7I(}=+&D3oac#unoTIIu%6Beb9C&HfDk~{#nOIgsp|kbVCFks}I`=fRH6t|f zC9elx@}l!DKj!ajjxy{%x+*tx?WW*L^P14l+rC;wg>F2xICtL6k4aajZcjQm>6KH| z+-LW)`p?e)YO!vA)9SFNJ6-F~uKZhP{Nai8q_df<3=JoDZ@6jQym@oQ)_wNECnH2Z z|L%SNrB8cO|IM9qtDiqU6L6^hn)iW>iFeLqeAIY!areXLZ7k<<)Hk0kU&huk?ZeC& zF9Ll(uWc$7DJcEYlmBII7_UKevHNGGP4iD&TDVdwBW>4?nOQrhN6uGQHd^v;$3CZY zzE}BIoQw_QR;uaDx*!_N5I%RqnfGquPG5Vn(k}(i^`H56pZi%4*Mm30zlzS?KJ!a` zNK0-{+$-x@rnz5ZCeBn#Up95-s>XFavFp~ITFrH9s(0D?HHqs>cHB5M^WU+HkN=a8C7Xw4m)3|o>;Z-`u6OF-*5KRzqre~Yn%} zL|ohx4@@E}px6rb%Jq+mzWWGX8vhQ`o!B*jT>Q zRnFy{R}w?*H%D*G;@S zZS}XzKd+wGatUw=JkQ#FMo6qad*_KoifdnO-7a!4quSW;)LOH>qW5p#{ueA39r;)0 zoyPq7#izm zKNa@f6|D}rz4cLl-=#8RzWNE$KS<%{Z-oy44HOEhn_(p!=aZV9}Fvs^Dl?YTj?}E?(e!&$NvZI%SktSW8T}nMrK2BgU8)h k%nT@CazCe+#DU$Ng#BiZg`~Uyb-}m{H`9+WRZM&&n`hWN0`S$kKx9|P4o>;QQu3O}oN22ZRurm4I z_4BI|^EaE@C{I>mef70!Z`JRPIx)}eWo9|G-@jJvwfp|HSjJz==Bd<*aP2cb57Ljl zr@Ht8MlM^)r>k;tc;5OJ%#JSiHPI-oNLXlP0q}!n|1Zx+Rq-w z(`4;uT|D#sQ)O6vvCQ3bkx|R+Peok(Z@IfT`);HwcgWWttNV@8=6$(X>*{vD`u2`g z;c1eI_r#}d-nigm;G;A5&&y2Q_xfjr&+pfne{SuWxSxxEg((ArTxoaxHN)4vO?_+$ zU-xa6kF~45aKpR&%XfF?{abfUQTt9z(`EhK^Y8QBuLiA-JSpR`erJcA!}|xDUuKGK@|u+{fBjUNc5sK&Mc%y= zE^Y2jKdi0X`bj5Ytx$IC**mZPEv~I!nPI=_``l|EL!F~G*DkvL`s*#X-?mrHYVJQj zG3Ui%DTPhzUlq!<&f4O4Xw8l#7lrpOvb_ENcWH_HWvF@LA_bi~>2eR0I2CHcz{ z7iC4|tuJF|tvzMeXIKB;I3=vd^NB+Jx9>AIyjc7B=0Vxe-&c3{W<89xdiQB!`qX_{ zTVLAO|E`%mlXI$?ru6wacm1{{@80#;{;^qIDEr=^-Fu_Ap6j`ARrKonP<_U8Zz|lg zProRSGQD`BI{xPVyM12OOH;yUH-xrkUE8O0d*`ERwW+=$C#P?|_8?Z)^6Wjga}}Sz zJkPrQeQsLsi*-3=eOdkYI8W!Swz};8^xEHe(+gAA|CHNX-@7sCOZBrt*GqHmUhlDc zl;K;leH{b$uTTaCh7bMEEh^2%^A*|vQ9 z`V(bFrk-DRXtgd6P41}|IbqGKHgE3tw;CeF*P;a{-gr2FzVhLJGj}dAR@az4Z=%#= z4Trtq6>iQsZqq9=jwa@6d;gJbf4sUi`PjygWiMstUd{*;uK2dQe4B8T=GoP9*HYuZ zbuUR)iKs1;f2Jqcr+ZtJbI+#Ue`QwlrsXf*_GYSFXY{7{i;6yY@E;2 zRnP2y89lkeWMcfW{4KZb!m=G!_qBfCj*=9PJ=0RkT5?P(Ra~~ytnX=(3@~exjx1T$HBH++9FNgezcTQy#>OZ<@ z{V>^?N%{85oX@c<85gPA2n*j`ow+Y`Lm$(+zIh+N?kf&sPRV|EW{dvbzb@1Gbgw$h zeEG=eYEixRW;=hk6pz1!wXMfwuH0YIYGfF6xoNzrcS(Ag zUFf#o?@X1AxsL5yHUDDe=_ToIH{9MY-M2XM^12z%cS@bMd9C&RGu`((ALg6#HTL~XL&J+-zWg!|-=h-{`Qjbt)(h1p%2DNv z>G`&4?i<{%wa$qA{iQEEEjKVSF8i8ny2;%CQSUTwTb@%Zd&ZEsrT+5j*mZN1e@pvX zF)%P3xF2`*;09&m?OX4^tDn!}A91<#n9CgPkjHcPTk>s@Rn7RKa{p|g&G*IYe@XMo z(P_{6_9Z{`7hRC?Tz9jAM~d}T zH7%+7xwh->l^J~wJb$A3gr&vrpU*dE*uAUYAIk0jWb9Fk+D;F#-7Ixn*Jd^!b&ZY}tv$Wp3g*qo~Zp{dN zZvQDSPOX01n}gq`X<2pcKdG~AQtm%3Z*|v8GA}#gH?mw6%}z~;W603kw&_vX=j}Zc zYgRK?f4A}9J5#Fi?eeRIy=R1Fckb$+wQOR&+LLvwx$dg!KCE1n9?QEqscv<#tGsB> zz1$Bc9yi|n>>~fwHLA5XwEpGicW-p+53TsH@)HlUrKLN#)-(Ux1zchY~SnC^XXsp-XHg_ zeVf1O#;I4&3*3Lo=rXsP2AEB=6xu9v^IL4(ukLlR|IeDNd$%N<>wVd^;{Gr1qUWb4 z=NRA4yy|!PxMf-Ro50+1vHFrJ+ZI3A9wza@W8wOeQ_IhU$k%tK_Pxv4KjGBB2jRMl zCRwhW>a#W{`RFWZ<)4%H2IODtwCj5Jzie_r>gO-F=N-#m>(di*@oJr0*~;cH$L=+s zrmuCa&a~!c%)F|X{?OO>9w-7#Hf#V(<=U{xYxt!CAQSbl*7^Iv5Qw%9LCZ9_cn|y;y(=!_);$sS- z!%jiyBnJqck^rR(pmYP2o&cp6K<}{%82l3MM%inErDyF#i9~!1Dh; z1Ji#-1|~So$iVWSnStd$8w1mSo=G<1(J%p42B!alND5&ZnHZS=vw)2SsbFSc{|};> z7+C)^GO+(=Vfg=_mx1X&3z*IHpP7O6KNADne<22@|3Z@sY((o}a*Y3(86cRAf$=}4 zsVq=gkgC57|Nk?A9S(6U$VPs!JZ{hMf#uo%|7T$T4+{+D|Lp4Eu=xF-f#Lsu7O>-3 z|8p}i{s&pX!NB;Ri{bx&WrlzMH_O<1vrOJ*Ej1dFqag`OZ=jSu@M$uW#gLid|9^Id z|NptbDH)Qh85tP=gD?}EW&&qRP|oL>oG2w;56bf(Z?J>2H7LU&>tOoN1T_^T5ArG~ zQ!+C!|7T`k`!5X5(5&Dr#rmI_feD;nz?qr>l*u7xu`@8j)glKK8v|oKh6Tt9K$#EZ zbWk3LITDn=L27V$3zRBh85j~IjQ=^oK?2F#AP=xIF#qRaVEoU`zzfUS|NqxB&e?p~ zDW1g}RHA`O7Z3&o56A@|HpmqquYkM>@-oOpAaP_GPr7B6K$wF$P^hhY33Z)AtpGy_5 zUkc%+ZG_T$q4Y^8eHBVSgwk)J^iK$#&I+Xkp)|}kO(-8)f2KP^`MwaEfuUXigeP~T KbxnSk<^ceQJv~AI delta 1713 zcmex+j&a*L#tChVGdH%s=U|*W`DUv0=1H9LjDnR6V35)ZrWjHtPJWmwJoze@j;9Jl z#QPnD4r_+ci9aE9iX@cQgwmE!+7n7gLg~!SUfe3G{45Or|Fbjv|Ifj|_@9U2-(&$B z5ng5nrvI!AO#j&!82|H5Hnb7fg^92-F#Z=}VEX@`f$2XZ5)G1PWBC6cB+oK=gPEv5 z<9}8L_WvvlO#hh~SpPFIu>BWeVEix4!1SL9suyHB$aY=^m|DjF%nT3=l0!Aq-%uRx zE|4t(lNoJ=Z9!^aF69U7W&i&lY%j=HjQ`mg82|GzF#cx&yMYzV2KkhW;s1Zt%@+() zSw;f@6bB1m;{xh)rXJlXmVkWJp=c^7Wkd2R$PNK;O2_SLP!56R1c-+bIRs=rD+BX?eun@5IT;xLgL4SO|Nr%j zvo=dP$Fq2Y90zg;2!lKb!XP#XgB;BQ@(=?f)RU+*Ob+Bo76!)2T3+`;Apy+Fzy=Ov zkSQPxG8KeDY!DtyCcp3oxeOEuAeVvIAPi!IFo`bR9P7Pba`H(|iOD9ZOBfeTzL}~d zm3j?QHm3_gX*npZ1uFgP85kJS;vgbvSx~wRN;g62J}5m4N-u-bo1pYQD18b_Lv2iZ Z1m#0(m9$?FemWb3W?-lnn7lmg8UVxS&ba^p diff --git a/game/src/ui/uiman.c b/game/src/ui/uiman.c index feb6d2e..fb9ee32 100644 --- a/game/src/ui/uiman.c +++ b/game/src/ui/uiman.c @@ -17,11 +17,13 @@ static mat4 projection; static Widget *hovered_widget = NULL; const char *lorem_ipsum = - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut " - "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " - "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit " - "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " - "culpa qui officia deserunt mollit anim id est laborum."; + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut " + "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " + "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit " + "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " + "culpa qui officia deserunt mollit anim id est laborum." + " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + "!@#$%^&*()_+{}[]'\";:,<.>/?\\|`~"; void uiman_init () diff --git a/game/src/ui/widget_layout.c b/game/src/ui/widget_layout.c index 0f70b7a..0d787e9 100644 --- a/game/src/ui/widget_layout.c +++ b/game/src/ui/widget_layout.c @@ -113,93 +113,103 @@ void Widget_layout_multiline_text (Widget *self) /* Vibe coded. Dunno what the fuck it does. */ { - if (self->multiline_text.lines) - { - for (guint i = 0; i < self->multiline_text.lines->len; ++i) - { - GString *old = g_array_index (self->multiline_text.lines, GString *, i); - g_string_free (old, TRUE); - } - - g_array_free (self->multiline_text.lines, TRUE); + if (self->multiline_text.lines) + { + for (unsigned int i = 0; i < self->multiline_text.lines->len; ++i) + { + GString *old = g_array_index (self->multiline_text.lines, GString *, i); + g_string_free (old, TRUE); + } + g_array_free (self->multiline_text.lines, TRUE); + } + + GArray *lines = g_array_new (FALSE, FALSE, sizeof (GString *)); + self->multiline_text.lines = lines; + + float pad = self->style->layout_padding; + float row_h = self->multiline_text.line_height; + float char_w = row_h * (9.0 / 20.0); + float usable = self->size[0] - 2 * pad; + + const char *p = self->multiline_text.text->str; + GString *cur = g_string_new (NULL); + float cur_w = 0.0; + + while (*p) + { + const char *end = p; + + while (*end && *end != ' ' && *end != '\n') + { + end++; + } + + gsize wb = end - p; + guint wc = g_utf8_strlen(p, wb); + float w = wc * char_w; + + gboolean too_long = (w > usable); + + if (cur_w > 0 && (*end == '\n' || (!too_long && cur_w + char_w + w > usable))) + { + g_array_append_val (lines, cur); + cur = g_string_new (NULL); + cur_w = 0.0; + } + + if (too_long) + { + const char *q = p; + while (q < end) + { + gunichar ch = g_utf8_get_char (q); + const char *next = g_utf8_next_char (q); + if (cur_w + char_w > usable) + { + g_array_append_val (lines, cur); + cur = g_string_new (NULL); + cur_w = 0.0f; + } + g_string_append_unichar (cur, ch); + cur_w += char_w; + q = next; + } + } + else + { + if (cur->len > 0 && *p != '\n') + { + g_string_append_c (cur, ' '); + cur_w += char_w; + } + g_string_append_len (cur, p, wb); + cur_w += w; + } + + if (*end == '\n') + { + g_array_append_val (lines, cur); + cur = g_string_new (NULL); + cur_w = 0.0; + p = end + 1; + } + else + { + p = end; + while (*p == ' ') p++; + } } - GArray *lines = g_array_new (FALSE, FALSE, sizeof (GString *)); - self->multiline_text.lines = lines; - - float pad = self->style->layout_padding; - float row_h = self->multiline_text.line_height; - float char_w = row_h * (9.0 / 20.0); - float usable = self->size[0] - 2 * pad; - - const char *p = self->multiline_text.text->str; - GString *cur = g_string_new (NULL); - float cur_w = 0.0; - - while (*p) - { - const char *end = p; - - while (*end && *end != ' ' && *end != '\n') - { - end++; - } - - size_t wb = end - p; - size_t wc = g_utf8_strlen (p, wb); - float w = wc * char_w; - - if (*end == '\n' || (cur_w > 0 && cur_w + char_w + w > usable)) - { - g_array_append_val (lines, cur); - cur = g_string_new (NULL); - cur_w = 0.0f; - } - - if (cur->len > 0 && *p != '\n') - { - g_string_append_c (cur, ' '); - cur_w += char_w; - } - - g_string_append_len (cur, p, wb); - cur_w += w; - - if (*end == '\n') - { - g_array_append_val (lines, cur); - cur = g_string_new (NULL); - cur_w = 0.0; - p = end + 1; - } - else - { - p = end; - while (*p == ' ') - { - p++; - } - } + if (cur->len > 0) { + g_array_append_val(lines, cur); + } else { + g_string_free(cur, TRUE); } - if (cur->len > 0) - { - g_array_append_val (lines, cur); - } - else - { - g_string_free (cur, TRUE); - } + self->size[1] = pad*2 + self->multiline_text.lines->len * row_h; + self->layout_dirty = FALSE; - self->size[1] = pad * 2 + lines->len * row_h; - self->layout_dirty = FALSE; - - /* Just a hack. In case the multiline text is inside a scrollable - (which, most of the time, would be the case) we have to update - the scrollable, so it can set it's content_size properly and the - scrollbar can be the right size. */ - if (self->parent) - { - self->parent->layout_dirty = TRUE; + if (self->parent) { + self->parent->layout_dirty = TRUE; } }