From 88ce951fda1099b6de97e8a7913ebd2a6f7b0c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr> Date: Wed, 17 Jul 2024 20:23:18 +0200 Subject: [PATCH] Clean / improve / update code --- android/gradle.properties | 4 +- assets/ui/button_back.png | Bin 3771 -> 2422 bytes assets/ui/button_delete_saved_game.png | Bin 5813 -> 7834 bytes assets/ui/button_resume_game.png | Bin 3659 -> 3434 bytes assets/ui/button_start.png | Bin 3999 -> 3058 bytes .../metadata/android/en-US/changelogs/63.txt | 1 + .../metadata/android/fr-FR/changelogs/63.txt | 1 + lib/config/default_game_settings.dart | 5 - lib/config/default_global_settings.dart | 5 - lib/ui/game/game_end.dart | 1 + lib/ui/helpers/app_titles.dart | 3 +- lib/ui/helpers/styled_button.dart | 210 ++++++++++++++++++ lib/ui/layouts/parameters_layout.dart | 73 +++--- lib/ui/parameters/parameter_image.dart | 39 ---- lib/ui/parameters/parameter_painter.dart | 46 +--- lib/ui/parameters/parameter_widget.dart | 120 ++++++++++ .../actions/button_delete_saved_game.dart | 10 +- lib/ui/widgets/actions/button_game_quit.dart | 10 +- .../actions/button_game_start_new.dart | 12 +- .../actions/button_resume_saved_game.dart | 10 +- lib/ui/widgets/global_app_bar.dart | 12 +- pubspec.lock | 116 +++++----- pubspec.yaml | 10 +- resources/app/build_application_resources.sh | 67 +++--- resources/build_resources.sh | 1 - resources/data/00_optimize_images.sh | 10 +- resources/data/build_images_assets_list.sh | 5 +- resources/data/check_sliced_images.sh | 2 +- resources/ui/build_ui_resources.sh | 49 ++-- resources/ui/images/button_back.svg | 2 +- .../ui/images/button_delete_saved_game.svg | 2 +- resources/ui/images/button_resume_game.svg | 2 +- resources/ui/images/button_start.svg | 2 +- 33 files changed, 550 insertions(+), 280 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/63.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/63.txt create mode 100644 lib/ui/helpers/styled_button.dart delete mode 100644 lib/ui/parameters/parameter_image.dart create mode 100644 lib/ui/parameters/parameter_widget.dart diff --git a/android/gradle.properties b/android/gradle.properties index 9b96205..188fa37 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.1.0 -app.versionCode=62 +app.versionName=0.1.1 +app.versionCode=63 diff --git a/assets/ui/button_back.png b/assets/ui/button_back.png index cc48ffb1dbb653d9a996f139dfbe02969724bfa5..51d7a01d171f7d7f047ecf9dee2d7ceee23b310d 100644 GIT binary patch literal 2422 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 TtA^&muK*w%B$~f6b-n&C1oC$E literal 3771 zcmYLMdpy(s_kV4+HMh)NLUbjJTuQmkWpW8~iA3m=DMCo*Zb>TZB192t$t5w7yUbEy zl;kokF@$o@{qFnrdHjCg?;o%C>w2z_bKd89?hvd_^7BaY008*SOpR@!xqf?~QP9`6 z*JlSbar>J(T?IhK2pWbkGW{?bI@}e6KNDnk#WRR>K9C4VBofxk@AB0P=lzM;D}fi& zr*tF%*lB8JY+xV4p3LyFw;z@M<aL#8t=p=q{`hgnCk<~6U;UsXmgybY;ksr?;GlOg z)<#FpyO&T}^D*1kC;SwXx|gyS?HRx=*e;=Dg7|LVefz{~bycn=wFXsn*{wd(UIYod z^riJ&rU0E5@}+;2G^#gOH&+KU76Ih5e?RTnz&09rlv$D-oy4jRr?IMM?@hz&cVo4c zjFc=~at^wEPWgqXETF&H*ZRmUePsEUPZTMr=#8%0yO!D9OWsdPp0p+%dl))s0+t(y zw}`ii`5Q0iu_=X_4=m=Kx|=!$-<OQ)!=&y{*YJ2JO(^6lp3Ul;@~$4`_vVS>2h$D2 zLe2esUe=1Q{6)JD1ccVIQsH+8_*#E&j<%b02(X6qxt2vcxW@C>-o3cj+n|-vlEX-c zM-<R{*W-NGnki_#1S+~*I#k?+IKrxx!(o<el87r;?{YPuY(J@KcK>O8m(W0TP`nQu zMnCkmmIQiAp!j}~L)TGby7o>c-9_9n2>)Ymt={B{b!*(iGmvUGT3#y`7JoX|ze;K6 zuKzyN;~ZA!)jBS5FyW9(@MI0|<)%TYHb=m}hGrz~X{wXzUpshw=jqI0HEFGXU@pkA z9iIj2?!n;1pqM+mo1NU(eT?Drr_)|2S^Ivh(8bxDsXA3ta5kmij4bOM$Oz@*lNWSm z{-G6Zh0U`av)->}Obo#r;PDZngRbL0@%(oxgmC>EjDUS8Wb!G}siJ`8lsi}I=2U#| zn*2q^Z;3p9d*|uPg{^l6<jlK?LVV~vSmS2tOP?!05<q14R3m#Nr{{>&GZcFym%YlC zrppM`pJNw)*6@>#<LZ2)72JO|Fh%17A2(<D?SvMJ%YH#J*(p<fKUw#Wy=EM|GgeoD z?oA-qX!kRH7zA?KZ}wxNr`s(xn2cBY!{46><X7=Ctsdg38@IStYr-<$THX6dAXhJ< zbOldFo?Fa^Z7lefDnIarNUNhxG!rw4`t^|v$@bab(W)ZP4xbruT9gB1fB`tbhr|IO z3!pWC@&*9_8~_+}2VMR5*yCj6j3NfW^KM*SB?g@mHwZ5qNXBU08`O{!kzVHeh>H8V z^RtF|$CqrCAl`g71_>h@X3oSp{>j!$4ED+if3Ih2tD&y*9tUKdnU&y>cjl1j`oIT& zk8v@=J_HD)9t;tcMyIKdaopNYvYp}|0l56_6GdNTxYMlPq!HTR>o<)W2x5S#@M4hO zb4qqdQB%D1x<NTI?xD@~ehCBc#4g*}P#al0Iya!Y^al<j@6S_J%GG6$MhdMDWWo6v zG(*5?jJbT9y21Xg$G_>%TxgL4Gj@zF<r#Cvuu)x<AOh53D^<P)TRwKXp^tX9zX9qG zC6A?kvziPtxc+k?>1L3(5l@$la?Y19-s3gld5vtdLeVmN$w;!^dV@C_z_K0u9SPM( zT?jM6pW2?!Wkr}duF}4Oc3*|4=sh11Hw^)r<Az1hsHY}%+QeepQTh(zCXJ4M3p&Ho zBI^U4G734r3(|*V!Hhx~<8oz8i-W%rLU%zwz3L8|?)?jLn8%kM1Po)^FXkea7jhj* znjTWjA29x&cSHZS0-Xmg`?&5oq2h5OvWPRaZi6^|Q7Tu_5rw#w)!xstKElSJLG2D_ zQ=#gZ8s7=N!^<a6R7qoPV)UODlB{omdTrzq?yHLd<0A6dMJJ{2%F@&wd*C=g6YceB z<0-0-*}aJ^V`+pcFGF!)TFTix8ZSv#S_+$y0|?9&O35bCT<DB{(xJB8*<U{GJX7@m zK?Z6)RHZP6v;+!T_pR|mTnfaiI6He0kh_dkDh=LO$nOd9R4#Mq4prIa8<NYhO0t3o zVB12d9KE-=w=v;F_t=430E7F=Q*@D1qJ^xWv4(4M^&p<M3Y8HR@)WTMh@XiY<Sy~v z@>gM7sBOhRin~Ck9~3Ivn57)Z_p;d>o^y<QTLxO9S5|tWk>b#s)BnCP;nDte`ff~1 z)Qukj%}N^_BY;+|<?!fwcu!9|*mN}WtRNtU<c`&kRFU4Xc`58EA*IS~ZO4yQ{$2W< z7{#~=Fz#AzyQr74>g|$m@%UZNt-T=t>)c27=EWii6<}g8&gCa1(?Tj1vDMIj6?u$i z>%_PPm||qnUgIM>pCn#|Sd0lj<Ab!yvjHM5=x63IW97<Eo(quZCTCC{lP>%=p&S)Q zg-p4|?cZLUW~-^b-_D=7D*`QR4eOzm#7fE4UFhwK84oI0$`^qBQUKwTD+F!cZI*WA z3)MGY@N5l)rstOyAtBMTqV<=~G(_Vag$+e(?(bd3;5Ok>JHxIoCDAz<8rwqMz~WTf zl5t$80!4SpS#BMJTZAY7N&OqO%93g_nvo-`A+&NRoXB2I-r`@rJPcYk5~epCYTm%` z+Kq`oKa+wjM=fQQYM{0a6_mY^3#u*;Lcv0~4|cr08p55h@!oS~i-3eYYfutW1S_WD zY{+ute-QFtRYo>6e-Bd*Mj&}$$#UQaO0dBWl>g<YxMOffoaMfi4Xg)8kG*dSoDwQG z!~r6j@XC$3by7v&RsM@~&35Qq=d;wh!fhKRX_jO6s7H_o_Dcm<Cg<IG%SB<<{uugM zU6ygmnA^y?+r-cSBos&$gR$7aP9f7lKiBP`k^g90ogv*w#R0lhlp=EyYg=0<0>z74 z*3LuuyssfEIFSu6<jmjhmccve%R(gUL5)|c>xHR1C?!9h&rtbb$>9cZ@)fn#nY4-R zT_pY+M>8+N`cdU`dHp)uC-`0PyrD#$;GEwq{Be7K8^6LlyZdMi?i?$-8$lCtO}^$x z32Y&*Pynnm)F$|*!SZSIA5%6sn>aA`PGK{hs^o(|?o}+m<n}NNBKrw<aZbKjD4(l4 ztJWo>kdlh{H=E>HOrz~wD;kA6CaagtAttr%wa0xOedwI+200c{dCkU^u~yM^OpzHn z9{jLlBq0Y45#IF}Ux0plL@^>nyDTy+4N-SQRmI-@j{o)$Kz`8cMA8i#WA@5h#TK%< z17B?6p<3b|gbyvdg#X?>(Fj>AOXd`^B+n}{mE0i@LQHR;P9||HGm~6rA|WF%xQTvw zUS(#!fJ#o<#-Yf4Fa#MSVwpr&?Dpdj3I!G5kSx#^`Jh@-sZS6F38n4%ljqjFmRag7 zHasO0ur0Da7w@EQlz_e?JZiJ@W#6Faw!#tTlIflF{So*lzVGzTZfg=jnGN`9$QF}0 zobj(_Pbq;H-$8)~LT$ay7=$DJ-gz2)jt;K~QDjO@Abf+*${>KAB2&STG8<cEpAzzT zb!`>N>wY+|Ziv1Esx1|+rJ}^40Yd}$(>rS-aM|R|=dRh*+O7PGrohF$(=*yNVLIac zh9I`R4e#`{kagVRLQ_|VHg$&7T}D`a(Q<OW0xCYA<4fe?7rid>PVJabrF~(Kq@(B+ z4JJ@Je!IW6b##!<4I@v)&vKesJB(Nz4{t|zJa>xDeXv<Ma=(8Ws-zjz*TQvFB@}-3 z00u1A$lqGABwM(gybkJVE<(@cAB<)DSmup(pyA-7&$|($xPvYM>ajqcxo;%d52|+G zl$oI}Hdg3)D;rO7!J~)${V=%e_!VA3hh*A!Pex>QamH&)3~2JkAHS5znJMMP_i(e# zGlUTYtqF&xKhvJP;L&%!Q|EE!#qSjyc;s(Izq=FldEmtRQc}pEzQuQgIo(`N{&_40 zce7K1nisp~(KKp4w-uxk=J15FV3B7|H@sF#2DmO9gg0dW4~(FJ?EjDm4hf%UReUbj zDMuQ?Ud3#Km}m5YQM2*RGknNAo^j!TPL|h}1rXHzc2vFj=5wIgz8FzLY1wQzMLv=- zu6G%NN&f<;krLWPIHE_$`t${PoMlhqY{8jDUHH6b%BVZEpZ9c#II^EynjMwy)q8>u zl?U(G7;ieqmeAdg%PLztHaQpkLsjZoJiJ!6Ys8PV?rjQ8tWC_gAsk1(&|j6v=oR4R zU<<eE*Ev5VFa(Vev-I2H!_iwPm{!owJyOU1F~zm_Z+^(A{6PHauMUIv;`z;%ML>Mi zs(9A{zP5EuxIcoO#9Mq2B(F@-b1TzYDi?#{5b{5p;+)mjcjG$jK)a;S6;f(?ifh)= zZiIWK6>GAw07GakX!~&QS1YZh)~Wl-VGu4FDD_I`a`loWAEqh1ozhaQUNFm-`e*vD zpe(sndPr*5fi6oD{k{P_RBhy12?V<nUd~;29$xQ;7wZvNt5?@DsdJVW`s-D%Ph_qy z&JWJ{B`sX6Xj%3}&bUveeGShmY1KK;h2r&?`!e11N{du;XsZdiELm9k>}boX@l!4? zRO04KR+4kZ7o7`7$KUL0UNl86hjqB%=M>9h?ZjJ${(6D^i=Cr=1Rt{%&B)=Lt_Zcy z7UTj62)l<@AC2yF4|CUz6IkCJF?GIofp&qvsN-6`kG4R+&I1#&!KV|}tOGrE6lUT1 zzg8kdj(X+mGQHHVm#tL}lf*TP3;CDs9&I#4Nc<|=%xST%;u#BGiU=IB-)@;AZA=bn zdr^r@Pc{Ad`?<;B|GTVI@#)Fm_nS3O=;<XjmUQ>`E;wSt`^D1Sjvy*Cr~OZjRrKUk z6(~O}iXSN}iWsT^GjT0DTQDs`srfr-o)(?8VNlQM(Xa(8Oc1MMP0eq&slW_xWn5(F G9`hgE`n)3m diff --git a/assets/ui/button_delete_saved_game.png b/assets/ui/button_delete_saved_game.png index 5e4f217689b11e444b7163557d7e5d68f3bbfe7d..4ca5b749c208c4b7eac2a4b141a1bd918d7cb98f 100644 GIT binary patch literal 7834 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 literal 5813 zcmbtYbySqkyMK3Gl$1tVa_MfAmRNA5YrkI*T)Lz|asfdRFzC*uS-O!>LQ1-HDUn7% zN*eCs{hfQx{qvst$Gmf9&df9O#OHbD{Y2_KQ70j!Cj<b11g7yw57&3xH2mARuimWF z9b8A?s$uE@0L&`5rVK*0^Wx(s={!|UJoTU3c=}knTLV5mK7#fxjvh!$S8KuN?zU+= z59tAbMj7@<$-wvfwwb-BfnhVe-TX4Bb#j>Ik)jSgS?ztzFqRoqy`&hy0e=y3|3gx? zFz&e50`<=nQW#VrFM}kN#kj4Q2~zY^))Xo5(RwhA5?+F}j9mjx_pMBZ5<NT)!}IdG zB$HzQ-D3TPHm^3z;4e`kt9U@>n{&6(>t)}>goRWce>s11FUzTjO~yGRz?F8^yEmdY zu@NqZtiwRnQBSAWE8dB$aWIQ~IS;1`dt#Lk+&*V<;y}(fClj{Oplx&JObK+jxnfxv z*#6;FsOnU#w|;X#!u}8PEG@714>L1}mk*ob;dv+K!y3f^X_;t(6XPdMN#a|mb5a+_ zl{>}^F~))%sRy2Sn&j#O-$U#S<I-Hq_Q#}7&jgTr)&ME>nZQqzmHf_A37JUsCg=K( zS&$P$FWo5wa=l&D;zUuOBUI#<fuFO|YU;TXYGHDDV<>UkTraZkcB*LqAAS)d+pZJ$ zw7@P2h%kMo<W?x<Ys+MdY|{&RC#K;+80+4k#riKQ&|o)SYqaj#xTd5Z@>z(@D!0EF zaw1&ZrBg`!Es!o(FcVeGxl8)R3jCFF);q>{s89rH&!tZAdjWby8Oo(F@@p@IRE+CY zw|m+ZW)4y`G?_6LEKU%2r}33`r8Bs62qulZ2XY`1O-kA}3$Y_zG#||g<l}RUs!p1X z0@}sY(qY{%K|A=!<t8fZ?;_F7xHQk#L4v}jD1X6lXm#pG^eqI$PM6yCArU2BqgYAk z6Pr0RQC)3R>cxbaYXGR>ntD-k$oZ0p8uWPdUY@WLimQWa_ddMNxt%P#%t^8P1DraU zv4fpWSzRirroTFAlR(Eq!nz^ofcEj-MY@4(cwUN((CL65IGHl+LRbXF6@vZvTn-fd zqcBc{2c^COVH@I@BwyUa+8$F`>H*ryE2o!uRChVShdk$g8FX=AUyA<rZx&1S3)rYR zNn#;v4Ha(Ah{JBzy@!`K!nZ0m)IP$@<3?79Q>N2G>8jclf9Kk+g&r`>1~j~=4kQBr zkRkv;I?w<M0HAOH0s{aJNB_^kqD|x8ykeq!g_M@>R<OxntsuXHgKeSWbhhKD#K!kz zBw02r*Y3!XfAvUk(8q+x+kQRo7sd7S5wsxxVa(2xkaD*^KX|h@Ki8wtmf%n6VF3J2 zlh#$&MeBXrHg-f+ycwTqv0&(2aj{Lg>^dU9*)?dJdWrc;9%H(*q+q$Dgo0XJXq}5J z{17mmDKr1&ZBE~^pss4pOO$pR+Gx8oc6D-B5%ucTmgDUz;7a^%#%NdyNyAK->|jJ1 z{~?C?V%~Z29tt2O-FyCUV0uNs)Krbpe?;9BQP$}5IW4%u2LyiTJByHtKYh{gED~!2 zBdIOel;n#fv6>zV{92wNHzEDoV}o9zM{`4tqJGFCXqKz7DG0xfl5Fu4o9&(!o2Uo- z;lfy<NAICaqTPEUGSN#Jqr~#7geLL;#0Aq`5&YjBA7l#)h1*KDPWxZOok@K3{Hr^3 zolU1cxBc4OPs#wBvAY^D{5Y9!(l2c^Hq<SrRoQ$Xx0ivtG);3#B3A&WujtL#$kv9( zQ`c{;V<&a%sr9-A2>k?KGpPfa04|n}Fx4euBG8UO8ns&SJ5rhoTcORZYJY2?YW{{p z0#;41L0TDPJz^IE0YCs*hago2)1XK%kIu=5=wY;w&E(3NAJwa@dlj}r!J`}g6RaLV z&)vSJk>8^_7EPEXtN3zIB^{jgi3Rn~D}iZJ>t@qoqO}RbQ97SnUrD}_f2GD>w8>@@ zJ&Q$3J%090UBOyr;hLn8NSv!`iwm)8=VwgTk>Tpx&6n6a*mg|!Hsal3>sI%_)W2nJ zfo35aUY1>@bd|sT85<79&6s=eK+K}mG#|O!40!c>Mt|pM6H|I5)K!w=FG})aByOp; z1}(=bu{ngP1nC&?xbHnpZXf>X^3;0M?TIV&n))}x73~4To^(_)Hp|TXu!OMb`l979 zlH32e2M{y&r&sPY|FBh@OI%7^UEJ6;bZ(T+{PfMpwAz!+UP0|&*+AeP?7_Wag7;)> ziI5y5ws^?CB)h7g!q$^x`(JMP(ruZWy?A`r(GO8vY`%{l(6pbDcv;)3r3)8CpSGrb zwe72f4)u%uG|b|<>a^#7NeM}@AX5yf+|#aJ_fan<E~sYFqSgOCyQ=S&VuLZj@DCaV zX0A`lFV%zsEGY0Zp2|h)x{JzM6I%U!>>N%WEOX8*It3k9uio_$^lKlz5QbYvVO-#C zlk@yS*IM`p&sHo|`;%#4vE==hZF14e7o*SdabBi+oidex_x8F~{NeiAcxre1Y1wL% z)HDhC)=s>SAAWwaT%Gu`Q|$Y2i+4X^)#?;qM#kkFmF~0lO-%3}RE;HDt9LZsW!BvU zz|#0{P$zeTqpKeH7^qQ-SJl}0<xi6FSv~ew)iqsj<m%oc5zsBdz~;_37DxoD2sfCK z3CG#~4s&5Wnn)ul+GZsA*ugL%7zGe=eDyP@H9FcBO_<XmiY@BPK(DFpPhYAxAiHyH zRU_SXJFfSxgG0}$_PxC4$AWUl8C26X#!O6;+1bPn5t(XPS-%OGOaQ5qEv3Ro=hS1Y z=kFZ&b_DztViJ0s{0)q0yKK>aPx7`8*kD;Z5tUN@R{b)wXyaUxdtN&s!4tC;OA|4n z*&S^4k80taO_m>P<7(fR(5{n?G(XP!gbY<3sfLrhUgBKNcviCYVuUOVpszZ3F*WnT zDEFbK^bX8EGJH__x$0@;bl-g)8SKRdqhw3NCbOlOe`I^{W-`rD-IPc;*2>ezv{|o= zu84e$skmAFg^hB}fISY(_}`3F;;glQ$|v_v&u*iKD!3URd^Fn&QgKJyD48xVzvU13 z6XgJQ)$7H7@4{)L>K(gunX=$SS+Nj%0oKXo+v%J(Jm!w9>6P%HX@%e{TJLyp^;!B& z=TI>*&WM6UjNjD!m<2+{{*>v<+t+v{#xA{R&42;|##UN2wR5`!Yo?M=hrHZ#tIXzi zWXDYFh|_@)eJaTN34#x9ROSy0MAPGij78eX-@%6So_y`g5-_rP*M#Jo`tIQ;3rG2_ zeatm59H-1y(%dJ}yY{KuWX4knv?Xux)o8`x6DV41^Oe1FeAn+PdR5ieJgf6%K1@x4 z6+!hqP0l+W$UX0>q{;n}m|I{wkd_++D+r{?y--OrJnlXJ!58JxcKe(N1(Y0JSPV2@ z_TEkSvCMcrxa8U<rQv11KJ$m)`x0XPR0o-F)5)t&K&GzC{zMeZZnJIj;kk~?YC!a} zjNl8gNtxx+*E<wjBU)6D5tCtk-_bw4*KX~?jHXLG0T=qe`uB4-Us67e=+gR}`j&#_ z>`0K`w_mK}IIfXPnIcu--^&u(t;z9o!!`7_dFh4}3P`4^DoC^k6ACfkQ}cqeQ5DLb z{gx3b9?DrZ`E_WU4n-Nwh+k~WFCjK>1491<q-cGaM4+_q*`1NF08mwZN<~w1QC`ym zNx#i;ek+8O*J;;s`O?NVKWLptTT~Ux?z?&a<S5HXy(aOf=26Y(VI?8}+^9yWL&1Qi zQz$G9=$I*-xGk5*CAI$c2_=fcRb)3t_g-C${qPb;yYSIz^ofNXuH;YKfr}P`&019K z$(fFsoTAp*R$KYY*Z4tJ?V1x%v(h3=c}%X;G(B!DO3fb3TQOPud7{<bb4of8ZXLdq zUPRrQze4$zLh*z%V7r{#p~bAgbi%0OHeYWj4FGYi3|#VTf}#+`?{)J(UaG?i>R+9t z?b+lkF%rh;5!BQ`$Y7X?Deiek{x%yr()NY|`Z9yLtMEhz(Jzd+R75`k8G+Iw+%6BB zTG467I=Q@do(~G~6%#U_Z5$mLtw0%@c&2uoTPNBzrs}urZ1Uy?pkx4~u@H*#TkY*n zfMuwz(dy;KvwmqGx`$1cRRJ8HaHj9>DkRZht%cUv1seVwxCo4b;}MDQnwFm}w?T~4 z5Xh5t4%x@pOcjQSNYO~UVA!RORw2Gl)`YCbNWtuPV-Jsq^vFd>9er7lLY2%24ofj3 zkoO*p5~{6g!%rnU^q{!nZK~k8c+39sJv*e)0q#J3nyK?KDc&-acHmCYq=o*ngYYIf zL;%1av4f+GOyYR?RKr)a7kIW@-u|lOKs$MxyS)UI<#}QeYYB!K_uA@aJtniZ@2)80 zd@P+$@EWlp0B5r|{GgYm8^!N#kw=iN+8a?Kt19}uj<gn+<sBtJZVZK$7BD)H+>daT zv$?0#yX|MY!6xN(o0DpkilyC_a}`8}l_e7v$nOMr3^#kUBtXsY)?Uli8XO%nL{w{a zGE+MSse&?gkEguO_+p?y9WuU78lB-1@T#8d*r@oET0J?T<V_4EIe_)NF;+qIm}Nr# zE5H77YH#Wh8D)TCq8Gsk4Q_jU_&e#Xbr+HijE7TsQ4g-z6GGY@XMQ%Z(oP(CzdeuG zQ0-jnfr_*;>I|I-kLv7tXG6r9nn=(8a}oMCNFBhNewQPe&6|S6+u`q6wuvp{%G_T9 zY{i`RZW<5F`uq7eCoR6nhuwr62Fh|hVXpP~YHk|MIY7m!7td$K1-p?BXgc&E81-_P zct)+9>BC76eg@ryb&mu1J5G5#h5L0ypN&ckEe)PMegU?(#ZMD-dP}CrS4=I^kX2jO z<nq8ouktU-3@Ar*7|o2-Fq3qj$-#Cps-<Nz&r>AcePVL`k3BS>-IBmEy%F6c$Z+D- zC`D7F|4LHj#8%U+#joW1$A*$1aL=jyR8(~>t(JYY)g9FmihKuMf7zRhjxOoMPV6&{ zYJPVMrE*jzNu(jVu^a*pY>QUZg~`gTs5XvS8Ekkv#|)8!b$ll!iw&nexM8_)mhM!I zbhClK;KM*W4BXB1snse*7o4PiBzi@-z663UV9(Pg90sMc@c>Zz6hwTrk3mv@j_$KL zcp}MUhNF)DK<g$l7b)NXrj?Q&;a|x2K;+-dig}YxbFj{5IMp|%xs7xo@XZ=tI3V+- zHYL;MkW=s^GlTUPC%`%TXy#}_{ya}tnPiFpr{m(49rzKqo2G5c@CUDm$|L}h|BYmY z{n656iqGLU4vU1cJTnj8SoJxgGf4|dC-`Sxj~eq$3l-p~7Zq*%t?)3}Tg~s;9YZzx z8;e<|qKXpO(JPSfDSAfi+rjD~vOg54MCnAdQ8pYtCcmA^Azxo)D1U>?V|7Zh^Q+~E zQekJm{lY7=zgoVJbA&l`&lu$IOq6MIb|YqcivP3redDEb6YpcBF-;C@<p!~(5NHgO zV@T-FTmC}Fzk&XP^tta{98x+iM<M8ds`OKTNA4<)b9d|er;l)ffU_T0on|?<^=XP~ zN<GERUGY*;@NvV4__knVXG!Hd8@>lB=_j9?|1f(RqYK1{QvRgNeip|tM5Uh9Hh(Gn zkyu@x^-ing_V@^N+8$(e9vOmzWdu~QZB*PV=>5?dxglC#wkjKzk<wK5X!L%3KOL3q zQ_)|R0#q2PaKGqwZ=Vg%dWi;CAANp`FXKU$BC#=2L9p~dhhwz`763mRLy%li-dWiD zo)et+wm>II5@8#M;yf6ksnV^>XKYUE*V&j3t=GwI4JtkmyG%20!B*u<$UBFs$7&#^ z(7V_UFqbElmas!gQSt2ub<;Zq<~XT~@1cw4dxx|6moG>424YbkFyTdJt7Wku_5CAx z%u1h6cJMt-$;Fl`n`{%B(eIh_>N5DI7f(HlYF61anhIRDX3SDMZsD>BPtmMW0YM|V zdrzt^)5zj!!xZU<GlJ^%578{uN0+Vhg$dG>*57{0YT$|g_p#YIvgxl#1SDv0ve$q( z$Z+}~)yXVy&In%XAFW4ZF*5sv09Qj8#~>4iz6i$A>C{2rzQSw~)rx(iT_OukjI$3R zu2_r+M%M3~>6H*Axg@LWGPt`(avLYLU+5@BFfEQFdWD?*UytQz<JZM|^Z$z4rGZqE zddXcoJMQhe_)#~_R0rznE8>1D%GkI}Wv4#g_tt7Lz`e5-JHJ_6#kW^`3XeZ*40}u{ zya^86{+06z+}vQ7;qtR=A#g<SfVCGK2E5HJr&5AO+Y8=t#-cg1@8A+r#6a#espThR zCfN!}HM}tG%<bF(N|Zih`tWk2X7K?Yh(7;rp8Ulp{j3DpF8C3PoX1FfIh!binihYN zihGPgycweb)va5@a4SqgC*VJ_jks$A9X{8m<W|1rRkKfm1-xQGjk9zo<*#TAob?iI zcWX&V!a?GR&2GA1$*cqI2TyizSv|Br+rE>i<TsjzW5TJP2i2pD>_^O~BT7jA7e9c* z8ICCc<ER3B9C46L1wa4*M<*x(I7$J>DEuD>cBv2xPP}pAmeptfLrw^JV}(CD4eLE7 zT-4>pwxn0RdGpCUx=NmU!AbZp9di1E1nP3$8VO){hqw8<&_L$Pexf^sjoS?@U|+h< z;Kw~TQzfs(U{>d$z-pJpQ=BN6@K&hMr84T{^4!^1B#w1aS8RX5U)rZVXQ&Mr8BMic ztQWZB_!;uMzefdD%Em^H?}1&DbA{9_-2rVB&%8p((9RZtPDa*#(^VcUnWdvONny6< z>nTsLJ~`^=XbI}4X);F#CQpI&dT_aZUQZ3ENd34RhGXnRbWvFOOUM1#KMT$WgkaZ; zDc@6KcQDGo{4!6F!-F9h%?kFNq_Gy_S!mysgc7@!e$NUk<r`ErjdI#HQw0X}xHs-d zccHNSf%R~U$)?Cc>v};>Kp=du&$5d1{)q)RWR=9Fb2Wa1)@A&91t0V=+59@5=g-=5 z?C~okMaU|FOG{7DfqhwRZC+xABPB|c;|-A?eO|Dpz_<07K1k|Z+yd>T2XBj8p1O+U zJPQay95GaYe(!rZwU=y={jKcultR8dhpYV(Qn~nHGrg;3#XrgLS!f8f{7}@$wmXAM zVTu`Bp9Cb5*<1EFAWw=tFX#dIPVunw7_FOZ40c^p-RV0k*kp7pJ?_LTf1%+8j%E}- z?NE`r;B9ArvHI^^gTc_xA~~rDz{?IfG`cNiE|aAb^xKS`(Rwi?1dBM$sWa>;%AzRC zC&4f{ei<UmzS~~T!?R!BH_0T~eHw0rm(g1y-INzE3y<GP|8$5g#4m&ZjJF$@s#&Y^ z-^69Dm*Pmgl%JO>Ct=5~F*&}FhSqD>sUR~Y;Gc_#JV*HH*Q&biCXW)L8cBn-^?ER> wbFp4U@=<-4b4k=>{l5+s$6)|4;`IA^po7F#|3l{pF4_T@>XS$1$`+yj1v#vpVE_OC diff --git a/assets/ui/button_resume_game.png b/assets/ui/button_resume_game.png index b2ea0a02d05e42377eb551a4b51428b511a32f5d..2fe433b7d18a39880a14e3f0af18cb75c4ccbaed 100644 GIT binary patch literal 3434 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 literal 3659 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 diff --git a/assets/ui/button_start.png b/assets/ui/button_start.png index 6845e2f5c21598ab61f1684d2075aeec0334bf23..23c7a4f670de19ffac455d6c510c3c53653a048b 100644 GIT binary patch literal 3058 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 literal 3999 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 Lv6WG|0fqi=I{^Hh diff --git a/fastlane/metadata/android/en-US/changelogs/63.txt b/fastlane/metadata/android/en-US/changelogs/63.txt new file mode 100644 index 0000000..5482b7f --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/63.txt @@ -0,0 +1 @@ +Clean / improve / update code and UI. diff --git a/fastlane/metadata/android/fr-FR/changelogs/63.txt b/fastlane/metadata/android/fr-FR/changelogs/63.txt new file mode 100644 index 0000000..8e88019 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/63.txt @@ -0,0 +1 @@ +Nettoyage / amélioration / mise à jour de code et de l'interface. diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart index b18afd1..7f9ba90 100644 --- a/lib/config/default_game_settings.dart +++ b/lib/config/default_game_settings.dart @@ -41,9 +41,4 @@ class DefaultGameSettings { printlog('Did not find any available value for game parameter "$parameterCode".'); return []; } - - // parameters displayed with assets (instead of painter) - static List<String> displayedWithAssets = [ - // - ]; } diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart index dac4541..11e641b 100644 --- a/lib/config/default_global_settings.dart +++ b/lib/config/default_global_settings.dart @@ -25,9 +25,4 @@ class DefaultGlobalSettings { printlog('Did not find any available value for global parameter "$parameterCode".'); return []; } - - // parameters displayed with assets (instead of painter) - static List<String> displayedWithAssets = [ - // - ]; } diff --git a/lib/ui/game/game_end.dart b/lib/ui/game/game_end.dart index ab071e1..e2aeae7 100644 --- a/lib/ui/game/game_end.dart +++ b/lib/ui/game/game_end.dart @@ -24,6 +24,7 @@ class GameEndWidget extends StatelessWidget { padding: const EdgeInsets.all(2), child: Table( defaultColumnWidth: const IntrinsicColumnWidth(), + defaultVerticalAlignment: TableCellVerticalAlignment.bottom, children: [ TableRow( children: [ diff --git a/lib/ui/helpers/app_titles.dart b/lib/ui/helpers/app_titles.dart index c3ddf3c..b98107b 100644 --- a/lib/ui/helpers/app_titles.dart +++ b/lib/ui/helpers/app_titles.dart @@ -11,8 +11,7 @@ class AppHeader extends StatelessWidget { return Text( tr(text), textAlign: TextAlign.start, - style: - Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), + style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), ); } } diff --git a/lib/ui/helpers/styled_button.dart b/lib/ui/helpers/styled_button.dart new file mode 100644 index 0000000..2000604 --- /dev/null +++ b/lib/ui/helpers/styled_button.dart @@ -0,0 +1,210 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; + +import 'package:puzzlegame/utils/color_extensions.dart'; + +class StyledButton extends StatelessWidget { + const StyledButton({ + super.key, + required this.color, + required this.onPressed, + this.onLongPress, + required this.child, + }); + + final Color color; + final VoidCallback? onPressed; + final VoidCallback? onLongPress; + final Widget child; + + factory StyledButton.text({ + Key? key, + required VoidCallback? onPressed, + VoidCallback? onLongPress, + required String caption, + required Color color, + }) { + final Widget captionWidget = AutoSizeText( + caption, + maxLines: 1, + style: TextStyle( + inherit: true, + fontWeight: FontWeight.w900, + color: color.darken(60), + shadows: [ + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(2, 2), + ), + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(2, -2), + ), + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(-2, 2), + ), + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(-2, -2), + ), + ], + ), + ); + + return StyledButton( + color: color, + onPressed: onPressed, + onLongPress: onLongPress, + child: captionWidget, + ); + } + + factory StyledButton.icon({ + Key? key, + required VoidCallback? onPressed, + VoidCallback? onLongPress, + required Icon icon, + required Color color, + required double iconSize, + }) { + return StyledButton( + color: color, + onPressed: onPressed, + onLongPress: onLongPress, + child: Icon( + icon.icon, + color: icon.color ?? color.darken(60), + size: iconSize, + shadows: [ + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(2, 2), + ), + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(2, -2), + ), + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(-2, 2), + ), + Shadow( + blurRadius: 5.0, + color: color.lighten(60), + offset: const Offset(-2, -2), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + const double borderWidth = 4; + final Color borderColor = color.darken(40); + const double borderRadius = 10; + + return Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + decoration: BoxDecoration( + color: color, + border: Border.all( + color: borderColor, + width: borderWidth, + ), + borderRadius: BorderRadius.circular(borderRadius), + ), + child: CustomPaint( + painter: StyledButtonPainter( + baseColor: color, + ), + child: MaterialButton( + onPressed: onPressed, + onLongPress: onLongPress, + padding: const EdgeInsets.all(8), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + minWidth: 40, + child: child, + ), + ), + ); + } +} + +class StyledButtonPainter extends CustomPainter { + StyledButtonPainter({ + required this.baseColor, + }); + + final Color baseColor; + + @override + void paint(Canvas canvas, Size size) { + final Color lightColor = baseColor.lighten(20); + final Color darkColor = baseColor.darken(20); + + final Paint paint = Paint()..style = PaintingStyle.fill; + + const double cornerRadius = 6; + + Path topPath = Path() + ..moveTo(cornerRadius, 0) + ..lineTo(size.width - cornerRadius, 0) + ..arcToPoint( + Offset(size.width, cornerRadius), + radius: const Radius.circular(cornerRadius), + ) + ..lineTo(size.width, size.height * .35) + ..quadraticBezierTo( + size.width * .4, + size.height * .1, + 0, + size.height * .3, + ) + ..lineTo(0, cornerRadius) + ..arcToPoint( + const Offset(cornerRadius, 0), + radius: const Radius.circular(cornerRadius), + ); + + Path bottomPath = Path() + ..moveTo(cornerRadius, size.height) + ..lineTo(size.width - cornerRadius, size.height) + ..arcToPoint( + Offset(size.width, size.height - cornerRadius), + radius: const Radius.circular(cornerRadius), + clockwise: false, + ) + ..lineTo(size.width, size.height * .7) + ..quadraticBezierTo( + size.width * .6, + size.height * .9, + 0, + size.height * .7, + ) + ..lineTo(0, size.height - cornerRadius) + ..arcToPoint( + Offset(cornerRadius, size.height), + radius: const Radius.circular(cornerRadius), + clockwise: false, + ); + + paint.color = lightColor; + canvas.drawPath(topPath, paint); + + paint.color = darkColor; + canvas.drawPath(bottomPath, paint); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => false; +} diff --git a/lib/ui/layouts/parameters_layout.dart b/lib/ui/layouts/parameters_layout.dart index 15aae81..c3bd214 100644 --- a/lib/ui/layouts/parameters_layout.dart +++ b/lib/ui/layouts/parameters_layout.dart @@ -5,8 +5,7 @@ import 'package:puzzlegame/config/default_game_settings.dart'; import 'package:puzzlegame/config/default_global_settings.dart'; import 'package:puzzlegame/cubit/settings_game_cubit.dart'; import 'package:puzzlegame/cubit/settings_global_cubit.dart'; -import 'package:puzzlegame/ui/parameters/parameter_image.dart'; -import 'package:puzzlegame/ui/parameters/parameter_painter.dart'; +import 'package:puzzlegame/ui/parameters/parameter_widget.dart'; import 'package:puzzlegame/ui/widgets/actions/button_delete_saved_game.dart'; import 'package:puzzlegame/ui/widgets/actions/button_game_start_new.dart'; import 'package:puzzlegame/ui/widgets/actions/button_resume_saved_game.dart'; @@ -35,21 +34,27 @@ class ParametersLayout extends StatelessWidget { lines.add(SizedBox(height: separatorHeight)); } - lines.add(SizedBox(height: separatorHeight)); + lines.add(Expanded( + child: SizedBox(height: separatorHeight), + )); if (canResume == false) { // Start new game - lines.add(const Expanded( - child: StartNewGameButton(), - )); + lines.add( + const AspectRatio( + aspectRatio: 3, + child: StartNewGameButton(), + ), + ); } else { // Resume game - lines.add(const Expanded( + lines.add(const AspectRatio( + aspectRatio: 3, child: ResumeSavedGameButton(), )); // Delete saved game lines.add(SizedBox.square( - dimension: MediaQuery.of(context).size.width / 4, + dimension: MediaQuery.of(context).size.width / 5, child: const DeleteSavedGameButton(), )); } @@ -102,44 +107,26 @@ class ParametersLayout extends StatelessWidget { ? globalSettingsCubit.getParameterValue(code) : gameSettingsCubit.getParameterValue(code); - final bool isActive = (value == currentValue); + final bool isSelected = (value == currentValue); final double displayWidth = MediaQuery.of(context).size.width; - final double itemWidth = displayWidth / availableValues.length - 26; - - final bool displayedWithAssets = - DefaultGlobalSettings.displayedWithAssets.contains(code) || - DefaultGameSettings.displayedWithAssets.contains(code); - - return TextButton( - child: Container( - child: displayedWithAssets - ? SizedBox.square( - dimension: itemWidth, - child: ParameterImage( - code: code, - value: value, - isSelected: isActive, - ), - ) - : CustomPaint( - size: Size(itemWidth, itemWidth), - willChange: false, - painter: ParameterPainter( - code: code, - value: value, - isSelected: isActive, - gameSettings: gameSettingsState.settings, - globalSettings: globalSettingsState.settings, - ), - isComplex: true, - ), + final double itemWidth = displayWidth / availableValues.length - 4; + + return SizedBox.square( + dimension: itemWidth, + child: ParameterWidget( + code: code, + value: value, + isSelected: isSelected, + size: itemWidth, + gameSettings: gameSettingsState.settings, + globalSettings: globalSettingsState.settings, + onPressed: () { + isGlobal + ? globalSettingsCubit.setParameterValue(code, value) + : gameSettingsCubit.setParameterValue(code, value); + }, ), - onPressed: () { - isGlobal - ? globalSettingsCubit.setParameterValue(code, value) - : gameSettingsCubit.setParameterValue(code, value); - }, ); }, ); diff --git a/lib/ui/parameters/parameter_image.dart b/lib/ui/parameters/parameter_image.dart deleted file mode 100644 index 1365189..0000000 --- a/lib/ui/parameters/parameter_image.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/material.dart'; - -class ParameterImage extends StatelessWidget { - const ParameterImage({ - super.key, - required this.code, - required this.value, - required this.isSelected, - }); - - final String code; - final String value; - final bool isSelected; - - static const Color buttonBackgroundColor = Colors.white; - static const Color buttonBorderColorActive = Colors.blue; - static const Color buttonBorderColorInactive = Colors.white; - static const double buttonBorderWidth = 8.0; - static const double buttonBorderRadius = 8.0; - - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: buttonBackgroundColor, - borderRadius: BorderRadius.circular(buttonBorderRadius), - border: Border.all( - color: - isSelected ? buttonBorderColorActive : buttonBorderColorInactive, - width: buttonBorderWidth, - ), - ), - child: Image( - image: AssetImage('assets/ui/${code}_$value.png'), - fit: BoxFit.fill, - ), - ); - } -} diff --git a/lib/ui/parameters/parameter_painter.dart b/lib/ui/parameters/parameter_painter.dart index 9ac8eea..cdb2e8d 100644 --- a/lib/ui/parameters/parameter_painter.dart +++ b/lib/ui/parameters/parameter_painter.dart @@ -11,14 +11,12 @@ class ParameterPainter extends CustomPainter { const ParameterPainter({ required this.code, required this.value, - required this.isSelected, required this.gameSettings, required this.globalSettings, }); final String code; final String value; - final bool isSelected; final GameSettings gameSettings; final GlobalSettings globalSettings; @@ -27,26 +25,14 @@ class ParameterPainter extends CustomPainter { // force square final double canvasSize = min(size.width, size.height); - const Color borderColorEnabled = Colors.blue; - const Color borderColorDisabled = Colors.white; - - // "enabled/disabled" border - final paint = Paint(); - paint.style = PaintingStyle.stroke; - paint.color = isSelected ? borderColorEnabled : borderColorDisabled; - paint.strokeJoin = StrokeJoin.round; - paint.strokeWidth = 10; - canvas.drawRect( - Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint); - // content switch (code) { case DefaultGameSettings.parameterCodeTilesetSize: - paintTilesetSizeParameterItem(value, canvas, canvasSize); + paintTilesetSizeParameterItem(canvas, canvasSize); break; default: printlog('Unknown parameter: $code/$value'); - paintUnknownParameterItem(value, canvas, canvasSize); + paintUnknownParameterItem(canvas, canvasSize); } } @@ -57,7 +43,6 @@ class ParameterPainter extends CustomPainter { // "unknown" parameter -> simple block with text void paintUnknownParameterItem( - final String value, final Canvas canvas, final double size, ) { @@ -65,12 +50,8 @@ class ParameterPainter extends CustomPainter { paint.strokeJoin = StrokeJoin.round; paint.strokeWidth = 3; - paint.color = Colors.grey; - paint.style = PaintingStyle.fill; - canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); - final textSpan = TextSpan( - text: '?\n$value', + text: '$code\n$value', style: const TextStyle( color: Colors.black, fontSize: 18, @@ -93,36 +74,15 @@ class ParameterPainter extends CustomPainter { } void paintTilesetSizeParameterItem( - final String value, final Canvas canvas, final double size, ) { - Color backgroundColor = Colors.grey; final int gridSize = int.parse(value.split('x')[0]); - switch (value) { - case DefaultGameSettings.tilesetSizeValueSmall: - backgroundColor = Colors.green; - break; - case DefaultGameSettings.tilesetSizeValueMedium: - backgroundColor = Colors.orange; - break; - case DefaultGameSettings.tilesetSizeValueLarge: - backgroundColor = Colors.red; - break; - default: - printlog('Wrong value for size parameter value: $value'); - } - final paint = Paint(); paint.strokeJoin = StrokeJoin.round; paint.strokeWidth = 3; - // Colored background - paint.color = backgroundColor; - paint.style = PaintingStyle.fill; - canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); - // Mini grid // TODO: add image final borderColor = Colors.grey.shade800; diff --git a/lib/ui/parameters/parameter_widget.dart b/lib/ui/parameters/parameter_widget.dart new file mode 100644 index 0000000..2eae5ad --- /dev/null +++ b/lib/ui/parameters/parameter_widget.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; + +import 'package:puzzlegame/config/default_game_settings.dart'; +import 'package:puzzlegame/config/default_global_settings.dart'; +import 'package:puzzlegame/models/settings/settings_game.dart'; +import 'package:puzzlegame/models/settings/settings_global.dart'; +import 'package:puzzlegame/ui/helpers/styled_button.dart'; +import 'package:puzzlegame/ui/parameters/parameter_painter.dart'; +import 'package:puzzlegame/utils/tools.dart'; + +class ParameterWidget extends StatelessWidget { + const ParameterWidget({ + super.key, + required this.code, + required this.value, + required this.isSelected, + required this.size, + required this.gameSettings, + required this.globalSettings, + required this.onPressed, + }); + + final String code; + final String value; + final bool isSelected; + final double size; + final GameSettings gameSettings; + final GlobalSettings globalSettings; + final VoidCallback onPressed; + + static const Color buttonColorActive = Colors.blue; + static const Color buttonColorInactive = Colors.white; + static const double buttonBorderWidth = 4.0; + static const double buttonBorderRadius = 12.0; + + @override + Widget build(BuildContext context) { + Widget content = const SizedBox.shrink(); + + switch (code) { + case DefaultGameSettings.parameterCodeTilesetSize: + content = getTilesetSizeParameterItem(); + break; + case DefaultGlobalSettings.parameterCodeSkin: + content = getSkinParameterItem(); + break; + default: + printlog('Unknown parameter: $code/$value'); + content = getUnknownParameterItem(); + } + + final Color buttonColor = isSelected ? buttonColorActive : buttonColorInactive; + + return Container( + decoration: BoxDecoration( + color: buttonColor, + borderRadius: BorderRadius.circular(buttonBorderRadius), + border: Border.all( + color: buttonColor, + width: buttonBorderWidth, + ), + ), + child: content, + ); + } + + // "unknown" parameter -> simple block with text + Widget getUnknownParameterItem() { + return StyledButton.text( + caption: '$code / $value', + color: Colors.grey, + onPressed: null, + ); + } + + Widget getTilesetSizeParameterItem() { + Color backgroundColor = Colors.grey; + + switch (value) { + case DefaultGameSettings.tilesetSizeValueSmall: + backgroundColor = Colors.green; + break; + case DefaultGameSettings.tilesetSizeValueMedium: + backgroundColor = Colors.orange; + break; + case DefaultGameSettings.tilesetSizeValueLarge: + backgroundColor = Colors.red; + break; + default: + printlog('Wrong value for size parameter value: $value'); + } + + return StyledButton( + color: backgroundColor, + onPressed: onPressed, + child: CustomPaint( + size: Size(size, size), + willChange: false, + painter: ParameterPainter( + code: code, + value: value, + gameSettings: gameSettings, + globalSettings: globalSettings, + ), + isComplex: true, + ), + ); + } + + Widget getSkinParameterItem() { + return StyledButton( + color: Colors.green.shade800, + onPressed: onPressed, + child: Image( + image: AssetImage('assets/ui/${DefaultGlobalSettings.parameterCodeSkin}_$value.png'), + fit: BoxFit.fill, + ), + ); + } +} diff --git a/lib/ui/widgets/actions/button_delete_saved_game.dart b/lib/ui/widgets/actions/button_delete_saved_game.dart index 564f0c2..053cfd3 100644 --- a/lib/ui/widgets/actions/button_delete_saved_game.dart +++ b/lib/ui/widgets/actions/button_delete_saved_game.dart @@ -2,20 +2,22 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:puzzlegame/cubit/game_cubit.dart'; +import 'package:puzzlegame/ui/helpers/styled_button.dart'; class DeleteSavedGameButton extends StatelessWidget { const DeleteSavedGameButton({super.key}); @override Widget build(BuildContext context) { - return TextButton( + return StyledButton( + color: Colors.grey, + onPressed: () { + BlocProvider.of<GameCubit>(context).deleteSavedGame(); + }, child: const Image( image: AssetImage('assets/ui/button_delete_saved_game.png'), fit: BoxFit.fill, ), - onPressed: () { - BlocProvider.of<GameCubit>(context).deleteSavedGame(); - }, ); } } diff --git a/lib/ui/widgets/actions/button_game_quit.dart b/lib/ui/widgets/actions/button_game_quit.dart index 5a11378..5a9f3f4 100644 --- a/lib/ui/widgets/actions/button_game_quit.dart +++ b/lib/ui/widgets/actions/button_game_quit.dart @@ -2,20 +2,22 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:puzzlegame/cubit/game_cubit.dart'; +import 'package:puzzlegame/ui/helpers/styled_button.dart'; class QuitGameButton extends StatelessWidget { const QuitGameButton({super.key}); @override Widget build(BuildContext context) { - return TextButton( + return StyledButton( + color: Colors.red, + onPressed: () { + BlocProvider.of<GameCubit>(context).quitGame(); + }, child: const Image( image: AssetImage('assets/ui/button_back.png'), fit: BoxFit.fill, ), - onPressed: () { - BlocProvider.of<GameCubit>(context).quitGame(); - }, ); } } diff --git a/lib/ui/widgets/actions/button_game_start_new.dart b/lib/ui/widgets/actions/button_game_start_new.dart index ce01705..61a2fca 100644 --- a/lib/ui/widgets/actions/button_game_start_new.dart +++ b/lib/ui/widgets/actions/button_game_start_new.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:puzzlegame/cubit/game_cubit.dart'; import 'package:puzzlegame/cubit/settings_game_cubit.dart'; import 'package:puzzlegame/cubit/settings_global_cubit.dart'; +import 'package:puzzlegame/ui/helpers/styled_button.dart'; class StartNewGameButton extends StatelessWidget { const StartNewGameButton({super.key}); @@ -14,17 +15,18 @@ class StartNewGameButton extends StatelessWidget { builder: (BuildContext context, GameSettingsState gameSettingsState) { return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>( builder: (BuildContext context, GlobalSettingsState globalSettingsState) { - return TextButton( - child: const Image( - image: AssetImage('assets/ui/button_start.png'), - fit: BoxFit.fill, - ), + return StyledButton( + color: Colors.blue, onPressed: () { BlocProvider.of<GameCubit>(context).startNewGame( gameSettings: gameSettingsState.settings, globalSettings: globalSettingsState.settings, ); }, + child: const Image( + image: AssetImage('assets/ui/button_start.png'), + fit: BoxFit.fill, + ), ); }, ); diff --git a/lib/ui/widgets/actions/button_resume_saved_game.dart b/lib/ui/widgets/actions/button_resume_saved_game.dart index b90f57b..b23dabd 100644 --- a/lib/ui/widgets/actions/button_resume_saved_game.dart +++ b/lib/ui/widgets/actions/button_resume_saved_game.dart @@ -2,20 +2,22 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:puzzlegame/cubit/game_cubit.dart'; +import 'package:puzzlegame/ui/helpers/styled_button.dart'; class ResumeSavedGameButton extends StatelessWidget { const ResumeSavedGameButton({super.key}); @override Widget build(BuildContext context) { - return TextButton( + return StyledButton( + color: Colors.blue, + onPressed: () { + BlocProvider.of<GameCubit>(context).resumeSavedGame(); + }, child: const Image( image: AssetImage('assets/ui/button_resume_game.png'), fit: BoxFit.fill, ), - onPressed: () { - BlocProvider.of<GameCubit>(context).resumeSavedGame(); - }, ); } } diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart index e2cfcb4..be38f02 100644 --- a/lib/ui/widgets/global_app_bar.dart +++ b/lib/ui/widgets/global_app_bar.dart @@ -6,6 +6,7 @@ import 'package:puzzlegame/cubit/game_cubit.dart'; import 'package:puzzlegame/cubit/nav_cubit.dart'; import 'package:puzzlegame/models/game/game.dart'; import 'package:puzzlegame/ui/helpers/app_titles.dart'; +import 'package:puzzlegame/ui/helpers/styled_button.dart'; class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget { const GlobalAppBar({super.key}); @@ -21,15 +22,16 @@ class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget { final List<Widget> menuActions = []; if (currentGame.isRunning && !currentGame.isFinished) { - menuActions.add(TextButton( - child: const Image( - image: AssetImage('assets/ui/button_back.png'), - fit: BoxFit.fill, - ), + menuActions.add(StyledButton( + color: Colors.red, onPressed: () {}, onLongPress: () { BlocProvider.of<GameCubit>(context).quitGame(); }, + child: const Image( + image: AssetImage('assets/ui/button_back.png'), + fit: BoxFit.fill, + ), )); } else { if (pageIndex == Menu.indexGame) { diff --git a/pubspec.lock b/pubspec.lock index b504a80..c593827 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" bloc: dependency: transitive description: @@ -61,10 +69,10 @@ packages: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" easy_localization: dependency: "direct main" description: @@ -93,18 +101,18 @@ packages: dependency: transitive description: name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" file: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" flutter: dependency: "direct main" description: flutter @@ -122,10 +130,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" flutter_localizations: dependency: transitive description: flutter @@ -148,10 +156,10 @@ packages: dependency: transitive description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_parser: dependency: transitive description: @@ -188,26 +196,26 @@ packages: dependency: transitive description: name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" nested: dependency: transitive description: @@ -220,18 +228,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 + sha256: "894f37107424311bdae3e476552229476777b8752c5a2a2369c0cb9a2d5442ef" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.0.3" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e + sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" path: dependency: transitive description: @@ -244,18 +252,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "9c96da072b421e98183f9ea7464898428e764bc0ce5567f27ec8693442e72514" + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a url: "https://pub.dev" source: hosted - version: "2.2.5" + version: "2.2.12" path_provider_foundation: dependency: transitive description: @@ -284,10 +292,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" petitparser: dependency: transitive description: @@ -324,58 +332,58 @@ packages: dependency: transitive description: name: shared_preferences - sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 + sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.3" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" + sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.5.3" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -393,18 +401,18 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" synchronized: dependency: transitive description: name: synchronized - sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" url: "https://pub.dev" source: hosted - version: "3.1.0+1" + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -425,10 +433,10 @@ packages: dependency: "direct main" description: name: unicons - sha256: dbfcf93ff4d4ea19b324113857e358e4882115ab85db04417a4ba1c72b17a670 + sha256: f3eab9d87c226415ef857cfd2167e1d12ad81ea1f5783b46cf644224fea4eab7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "3.0.0" vector_math: dependency: transitive description: @@ -441,26 +449,26 @@ packages: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.1.0" win32: dependency: transitive description: name: win32 - sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 + sha256: "4d45dc9069dba4619dc0ebd93c7cec5e66d8482cb625a370ac806dcc8165f2ec" url: "https://pub.dev" source: hosted - version: "5.5.1" + version: "5.5.5" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" xml: dependency: transitive description: @@ -470,5 +478,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.4.0 <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index 5b25af4..fc52e0d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A puzzle game application. publish_to: "none" -version: 0.1.0+62 +version: 0.1.1+63 environment: sdk: "^3.0.0" @@ -13,6 +13,7 @@ dependencies: sdk: flutter # base + auto_size_text: ^3.0.0 easy_localization: ^3.0.1 equatable: ^2.0.5 flutter_bloc: ^8.1.1 @@ -20,20 +21,20 @@ dependencies: hydrated_bloc: ^9.0.0 package_info_plus: ^8.0.0 path_provider: ^2.0.11 - unicons: ^2.1.1 + unicons: ^3.0.0 # specific image: ^4.1.3 dev_dependencies: - flutter_lints: ^4.0.0 + flutter_lints: ^5.0.0 flutter: uses-material-design: true assets: - assets/images/ - - assets/ui/ - assets/translations/ + - assets/ui/ fonts: - family: Nunito @@ -46,4 +47,3 @@ flutter: weight: 400 - asset: assets/fonts/Nunito-Light.ttf weight: 300 - diff --git a/resources/app/build_application_resources.sh b/resources/app/build_application_resources.sh index 6d67b8f..1ace90d 100755 --- a/resources/app/build_application_resources.sh +++ b/resources/app/build_application_resources.sh @@ -1,9 +1,18 @@ #! /bin/bash # Check dependencies -command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; } -command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; } -command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; } +command -v inkscape >/dev/null 2>&1 || { + echo >&2 "I require inkscape but it's not installed. Aborting." + exit 1 +} +command -v scour >/dev/null 2>&1 || { + echo >&2 "I require scour but it's not installed. Aborting." + exit 1 +} +command -v optipng >/dev/null 2>&1 || { + echo >&2 "I require optipng but it's not installed. Aborting." + exit 1 +} CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")" @@ -31,14 +40,14 @@ function optimize_svg() { cp ${SVG} ${SVG}.tmp scour \ - --remove-descriptive-elements \ - --enable-id-stripping \ - --enable-viewboxing \ - --enable-comment-stripping \ - --nindent=4 \ - --quiet \ - -i ${SVG}.tmp \ - -o ${SVG} + --remove-descriptive-elements \ + --enable-id-stripping \ + --enable-viewboxing \ + --enable-comment-stripping \ + --nindent=4 \ + --quiet \ + -i ${SVG}.tmp \ + -o ${SVG} rm ${SVG}.tmp } @@ -57,10 +66,10 @@ function build_application_icon() { TARGET_PNG="${TARGET}.png" inkscape \ - --export-width=${ICON_SIZE} \ - --export-height=${ICON_SIZE} \ - --export-filename=${TARGET_PNG} \ - ${SOURCE_ICON} + --export-width=${ICON_SIZE} \ + --export-height=${ICON_SIZE} \ + --export-filename=${TARGET_PNG} \ + ${SOURCE_ICON} optipng ${OPTIPNG_OPTIONS} ${TARGET_PNG} } @@ -76,10 +85,10 @@ function build_fastlane_image() { TARGET_PNG="${TARGET}.png" inkscape \ - --export-width=${WIDTH} \ - --export-height=${HEIGHT} \ - --export-filename=${TARGET_PNG} \ - ${SOURCE_FASTLANE} + --export-width=${WIDTH} \ + --export-height=${HEIGHT} \ + --export-filename=${TARGET_PNG} \ + ${SOURCE_FASTLANE} optipng ${OPTIPNG_OPTIONS} ${TARGET_PNG} } @@ -94,24 +103,24 @@ function build_launch_image() { TARGET_PNG="${TARGET}.png" inkscape \ - --export-width=${ICON_SIZE} \ - --export-height=${ICON_SIZE} \ - --export-filename=${TARGET_PNG} \ - ${SOURCE_LAUNCH_IMAGE} + --export-width=${ICON_SIZE} \ + --export-height=${ICON_SIZE} \ + --export-filename=${TARGET_PNG} \ + ${SOURCE_LAUNCH_IMAGE} optipng ${OPTIPNG_OPTIONS} ${TARGET_PNG} } -build_application_icon 72 ${BASE_DIR}/android/app/src/main/res/mipmap-hdpi/ic_launcher -build_application_icon 48 ${BASE_DIR}/android/app/src/main/res/mipmap-mdpi/ic_launcher -build_application_icon 96 ${BASE_DIR}/android/app/src/main/res/mipmap-xhdpi/ic_launcher +build_application_icon 72 ${BASE_DIR}/android/app/src/main/res/mipmap-hdpi/ic_launcher +build_application_icon 48 ${BASE_DIR}/android/app/src/main/res/mipmap-mdpi/ic_launcher +build_application_icon 96 ${BASE_DIR}/android/app/src/main/res/mipmap-xhdpi/ic_launcher build_application_icon 144 ${BASE_DIR}/android/app/src/main/res/mipmap-xxhdpi/ic_launcher build_application_icon 192 ${BASE_DIR}/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher build_application_icon 512 ${BASE_DIR}/fastlane/metadata/android/en-US/images/icon -build_launch_image 72 ${BASE_DIR}/android/app/src/main/res/mipmap-hdpi/launch_image -build_launch_image 48 ${BASE_DIR}/android/app/src/main/res/mipmap-mdpi/launch_image -build_launch_image 96 ${BASE_DIR}/android/app/src/main/res/mipmap-xhdpi/launch_image +build_launch_image 72 ${BASE_DIR}/android/app/src/main/res/mipmap-hdpi/launch_image +build_launch_image 48 ${BASE_DIR}/android/app/src/main/res/mipmap-mdpi/launch_image +build_launch_image 96 ${BASE_DIR}/android/app/src/main/res/mipmap-xhdpi/launch_image build_launch_image 144 ${BASE_DIR}/android/app/src/main/res/mipmap-xxhdpi/launch_image build_launch_image 192 ${BASE_DIR}/android/app/src/main/res/mipmap-xxxhdpi/launch_image diff --git a/resources/build_resources.sh b/resources/build_resources.sh index 41cf772..d4d88e0 100755 --- a/resources/build_resources.sh +++ b/resources/build_resources.sh @@ -5,4 +5,3 @@ CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" ${CURRENT_DIR}/app/build_application_resources.sh ${CURRENT_DIR}/ui/build_ui_resources.sh ${CURRENT_DIR}/data/build_images_assets_list.sh - diff --git a/resources/data/00_optimize_images.sh b/resources/data/00_optimize_images.sh index 7627a74..9e197a0 100755 --- a/resources/data/00_optimize_images.sh +++ b/resources/data/00_optimize_images.sh @@ -1,7 +1,13 @@ #!/usr/bin/env bash -command -v convert >/dev/null 2>&1 || { echo >&2 "I require convert (imagemagick) but it's not installed. Aborting."; exit 1; } -command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; } +command -v convert >/dev/null 2>&1 || { + echo >&2 "I require convert (imagemagick) but it's not installed. Aborting." + exit 1 +} +command -v optipng >/dev/null 2>&1 || { + echo >&2 "I require optipng but it's not installed. Aborting." + exit 1 +} CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" diff --git a/resources/data/build_images_assets_list.sh b/resources/data/build_images_assets_list.sh index ddafcb2..b4fc566 100755 --- a/resources/data/build_images_assets_list.sh +++ b/resources/data/build_images_assets_list.sh @@ -1,6 +1,9 @@ #!/usr/bin/env bash -command -v jq >/dev/null 2>&1 || { echo >&2 "I require jq (json parser) but it's not installed. Aborting."; exit 1; } +command -v jq >/dev/null 2>&1 || { + echo >&2 "I require jq (json parser) but it's not installed. Aborting." + exit 1 +} CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")" diff --git a/resources/data/check_sliced_images.sh b/resources/data/check_sliced_images.sh index 6dd8b1c..33efefb 100755 --- a/resources/data/check_sliced_images.sh +++ b/resources/data/check_sliced_images.sh @@ -101,6 +101,6 @@ HTML_CONTENT=" </html> " -echo "${HTML_CONTENT}" > "${HTML_OUTPUT_FiLE}" +echo "${HTML_CONTENT}" >"${HTML_OUTPUT_FiLE}" echo "done." diff --git a/resources/ui/build_ui_resources.sh b/resources/ui/build_ui_resources.sh index 4f365ed..4fa137a 100755 --- a/resources/ui/build_ui_resources.sh +++ b/resources/ui/build_ui_resources.sh @@ -1,9 +1,18 @@ #! /bin/bash # Check dependencies -command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; } -command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; } -command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; } +command -v inkscape >/dev/null 2>&1 || { + echo >&2 "I require inkscape but it's not installed. Aborting." + exit 1 +} +command -v scour >/dev/null 2>&1 || { + echo >&2 "I require scour but it's not installed. Aborting." + exit 1 +} +command -v optipng >/dev/null 2>&1 || { + echo >&2 "I require optipng but it's not installed. Aborting." + exit 1 +} CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" BASE_DIR="$(dirname "$(dirname "${CURRENT_DIR}")")" @@ -40,14 +49,14 @@ function optimize_svg() { cp ${SOURCE} ${SOURCE}.tmp scour \ - --remove-descriptive-elements \ - --enable-id-stripping \ - --enable-viewboxing \ - --enable-comment-stripping \ - --nindent=4 \ - --quiet \ - -i ${SOURCE}.tmp \ - -o ${SOURCE} + --remove-descriptive-elements \ + --enable-id-stripping \ + --enable-viewboxing \ + --enable-comment-stripping \ + --nindent=4 \ + --quiet \ + -i ${SOURCE}.tmp \ + -o ${SOURCE} rm ${SOURCE}.tmp } @@ -68,10 +77,10 @@ function build_image() { mkdir -p "$(dirname "${TARGET}")" inkscape \ - --export-width=${ICON_SIZE} \ - --export-height=${ICON_SIZE} \ - --export-filename=${TARGET} \ - "${SOURCE}" + --export-width=${ICON_SIZE} \ + --export-height=${ICON_SIZE} \ + --export-filename=${TARGET} \ + "${SOURCE}" optipng ${OPTIPNG_OPTIONS} "${TARGET}" } @@ -80,8 +89,7 @@ function build_image_for_skin() { SKIN_CODE="$1" # skin images - for SKIN_IMAGE in ${SKIN_IMAGES} - do + for SKIN_IMAGE in ${SKIN_IMAGES}; do build_image ${CURRENT_DIR}/skins/${SKIN_CODE}/${SKIN_IMAGE}.svg ${ASSETS_DIR}/skins/${SKIN_CODE}_${SKIN_IMAGE}.png done } @@ -97,14 +105,11 @@ if [ -d "${ASSETS_DIR}/skins" ]; then fi # build game images -for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES} -do +for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}; do build_image ${CURRENT_DIR}/images/${GAME_IMAGE}.svg ${ASSETS_DIR}/ui/${GAME_IMAGE}.png done # build skins images -for SKIN in ${AVAILABLE_SKINS} -do +for SKIN in ${AVAILABLE_SKINS}; do build_image_for_skin "${SKIN}" done - diff --git a/resources/ui/images/button_back.svg b/resources/ui/images/button_back.svg index 2622a57..018d8b7 100644 --- a/resources/ui/images/button_back.svg +++ b/resources/ui/images/button_back.svg @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#e41578" stroke="#fff" stroke-width=".238"/><path d="m59.387 71.362c1.1248 1.1302 4.0012 1.1302 4.0012 0v-45.921c0-1.1316-2.8832-1.1316-4.0121 0l-37.693 20.918c-1.1289 1.1248-1.1479 2.9551-0.02171 4.084z" fill="#fefeff" stroke="#930e4e" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m57.857 68.048c0.96243 0.96706 3.4236 0.96706 3.4236 0v-39.292c0-0.96825-2.467-0.96825-3.4329 0l-32.252 17.898c-0.96594 0.96243-0.9822 2.5285-0.01858 3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg> +<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path transform="matrix(1.3783 .61747 -.61747 1.3783 45.198 93.762)" d="m11.645-14.603-44.77-4.6003 26.369-36.472z" fill="#fff" stroke="#950e4f" stroke-linecap="round" stroke-linejoin="round" stroke-width="7.2832"/></svg> diff --git a/resources/ui/images/button_delete_saved_game.svg b/resources/ui/images/button_delete_saved_game.svg index ac7eefe..c3f872e 100644 --- a/resources/ui/images/button_delete_saved_game.svg +++ b/resources/ui/images/button_delete_saved_game.svg @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#ee7d49" stroke="#fff" stroke-width=".238"/><path d="m61.07 35.601-1.7399 27.837c-0.13442 2.1535-1.9205 3.8312-4.0781 3.8312h-16.84c-2.1576 0-3.9437-1.6777-4.0781-3.8312l-1.7399-27.837h-2.6176c-0.84621 0-1.5323-0.68613-1.5323-1.5323 0-0.84655 0.68613-1.5323 1.5323-1.5323h33.711c0.84621 0 1.5323 0.68578 1.5323 1.5323 0 0.84621-0.68613 1.5323-1.5323 1.5323zm-3.2617 0h-21.953l1.4715 26.674c0.05985 1.0829 0.95531 1.9305 2.0403 1.9305h14.929c1.085 0 1.9804-0.84757 2.0403-1.9305zm-10.977 3.0647c0.78977 0 1.4301 0.6403 1.4301 1.4301v19.614c0 0.78977-0.6403 1.4301-1.4301 1.4301s-1.4301-0.6403-1.4301-1.4301v-19.614c0-0.78977 0.6403-1.4301 1.4301-1.4301zm-6.1293 0c0.80004 0 1.4588 0.62935 1.495 1.4286l0.89647 19.719c0.03182 0.70016-0.50998 1.2933-1.2101 1.3255-0.01915 7.02e-4 -0.03831 1e-3 -0.05781 1e-3 -0.74462 0-1.3596-0.58215-1.4003-1.3261l-1.0757-19.719c-0.0407-0.74701 0.53188-1.3852 1.2786-1.4259 0.02462-0.0014 0.04926-2e-3 0.07388-2e-3zm12.259 0c0.74804 0 1.3541 0.60609 1.3541 1.3541 0 0.02462-3.28e-4 0.04926-0.0017 0.07388l-1.0703 19.618c-0.04379 0.80106-0.70597 1.4281-1.5081 1.4281-0.74804 0-1.3541-0.60609-1.3541-1.3541 0-0.02462 3.49e-4 -0.04925 0.0017-0.07388l1.0703-19.618c0.04379-0.80106 0.70597-1.4281 1.5081-1.4281zm-10.216-12.259h8.1728c2.2567 0 4.086 1.8293 4.086 4.086v2.0433h-16.344v-2.0433c0-2.2567 1.8293-4.086 4.086-4.086zm0.20453 3.0647c-0.67725 0-1.2259 0.54863-1.2259 1.2259v1.8388h10.215v-1.8388c0-0.67725-0.54863-1.2259-1.2259-1.2259z" fill="#fff" fill-rule="evenodd" stroke="#bd4812" stroke-width=".75383"/></svg> +<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m76.652 23.303-3.6441 58.302c-0.28153 4.5103-4.0223 8.0241-8.5413 8.0241h-35.27c-4.5189 0-8.2598-3.5138-8.5413-8.0241l-3.6441-58.302h-5.4824c-1.7723 0-3.2093-1.437-3.2093-3.2093 0-1.773 1.437-3.2093 3.2093-3.2093h70.605c1.7723 0 3.2093 1.4363 3.2093 3.2093 0 1.7723-1.437 3.2093-3.2093 3.2093zm-6.8314 0h-45.979l3.0819 55.867c0.12535 2.268 2.0008 4.0433 4.2732 4.0433h31.268c2.2724 0 4.1478-1.7752 4.2732-4.0433zm-22.99 6.4188c1.6541 0 2.9952 1.3411 2.9952 2.9952v41.08c0 1.6541-1.3411 2.9952-2.9952 2.9952-1.6542 0-2.9952-1.3411-2.9952-2.9952v-41.08c0-1.6541 1.3411-2.9952 2.9952-2.9952zm-12.837 0c1.6756 0 3.0553 1.3181 3.1312 2.9921l1.8776 41.3c0.06665 1.4664-1.0681 2.7087-2.5345 2.7762-0.04011 0.0015-0.08024 0.0021-0.12108 0.0021-1.5595 0-2.8476-1.2193-2.9328-2.7774l-2.253-41.3c-0.08524-1.5646 1.114-2.9012 2.6779-2.9864 0.05157-0.0029 0.10317-0.0042 0.15474-0.0042zm25.675 0c1.5667 0 2.8361 1.2694 2.8361 2.8361 0 0.05156-6.87e-4 0.10317-0.0036 0.15474l-2.2416 41.088c-0.09171 1.6778-1.4786 2.991-3.1586 2.991-1.5667 0-2.8361-1.2694-2.8361-2.8361 0-0.05156 7.31e-4 -0.10315 0.0036-0.15474l2.2417-41.088c0.09172-1.6778 1.4786-2.991 3.1586-2.991zm-21.397-25.675h17.117c4.7265 0 8.5578 3.8313 8.5578 8.5578v4.2795h-34.231v-4.2795c0-4.7265 3.8313-8.5578 8.5578-8.5578zm0.42837 6.4188c-1.4184 0-2.5675 1.1491-2.5675 2.5675v3.8512h21.394v-3.8512c0-1.4184-1.1491-2.5675-2.5675-2.5675z" fill="#fff" fill-rule="evenodd" stroke="#050200"/></svg> diff --git a/resources/ui/images/button_resume_game.svg b/resources/ui/images/button_resume_game.svg index 6ad8b64..2bf9732 100644 --- a/resources/ui/images/button_resume_game.svg +++ b/resources/ui/images/button_resume_game.svg @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m39.211 31.236c-0.84086-0.84489-2.9911-0.84489-2.9911 0v34.329c0 0.84594 2.1554 0.84594 2.9993 0l28.178-15.637c0.84392-0.84086 0.85812-2.2091 0.01623-3.053z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.1726"/><path d="m40.355 33.714c-0.71948-0.72294-2.5594-0.72294-2.5594 0v29.373c0 0.72383 1.8442 0.72383 2.5663 0l24.11-13.38c0.7221-0.71948 0.73426-1.8902 0.01389-2.6124z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.225"/><path d="m28.369 66.919v-37.591" fill="#105ca2" stroke="#105ca2" stroke-linecap="round" stroke-width="4.0337"/></svg> +<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-5.618)" fill="#fff" stroke="#105ea2" stroke-linecap="round" stroke-linejoin="round"><path transform="matrix(-1.3783 -.61747 .61747 -1.3783 55.567 -.086035)" d="m11.645-14.603-44.77-4.6003 26.369-36.472z" stroke-width="7.2832"/><path d="m15.535 12.852 2e-3 67.973z" stroke-width="11"/></g></svg> diff --git a/resources/ui/images/button_start.svg b/resources/ui/images/button_start.svg index e9d49d2..4d7634a 100644 --- a/resources/ui/images/button_start.svg +++ b/resources/ui/images/button_start.svg @@ -1,2 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg> +<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path transform="matrix(-1.3783 -.61747 .61747 -1.3783 46.954 -.086035)" d="m11.645-14.603-44.77-4.6003 26.369-36.472z" fill="#fff" stroke="#105ea2" stroke-linecap="round" stroke-linejoin="round" stroke-width="7.2832"/></svg> -- GitLab