From 531d5bdb6ff2437d504afdeaf7d6a34cb17d54f3 Mon Sep 17 00:00:00 2001 From: Jenny Diomidova Date: Wed, 10 Dec 2025 16:06:21 +0100 Subject: [PATCH] add a python script to automatic generate all screenshots --- assets/screenshots/chalk.png | Bin 2061 -> 0 bytes assets/screenshots/diorite.png | Bin 1427 -> 0 bytes flake.lock | 32 +++-- flake.nix | 13 +- screenshots/basalt/01_white-black-black.png | Bin 0 -> 1414 bytes screenshots/basalt/02_black-white-gray.png | Bin 0 -> 1222 bytes screenshots/basalt/03_yellow-blue-blue.png | Bin 0 -> 1101 bytes screenshots/chalk/01_white-black-black.png | Bin 0 -> 1896 bytes screenshots/chalk/02_black-white-gray.png | Bin 0 -> 1351 bytes screenshots/chalk/03_yellow-blue-blue.png | Bin 0 -> 1556 bytes screenshots/diorite/01_white-black-black.png | Bin 0 -> 1414 bytes screenshots/diorite/02_black-white-gray.png | Bin 0 -> 1348 bytes src/c/digit_layer.cpp | 3 + src/c/digit_layer.hpp | 11 +- src/c/main.cpp | 36 +++-- src/c/settings.cpp | 7 +- take_screenshots.py | 141 +++++++++++++++++++ 17 files changed, 203 insertions(+), 40 deletions(-) delete mode 100644 assets/screenshots/chalk.png delete mode 100644 assets/screenshots/diorite.png create mode 100644 screenshots/basalt/01_white-black-black.png create mode 100644 screenshots/basalt/02_black-white-gray.png create mode 100644 screenshots/basalt/03_yellow-blue-blue.png create mode 100644 screenshots/chalk/01_white-black-black.png create mode 100644 screenshots/chalk/02_black-white-gray.png create mode 100644 screenshots/chalk/03_yellow-blue-blue.png create mode 100644 screenshots/diorite/01_white-black-black.png create mode 100644 screenshots/diorite/02_black-white-gray.png create mode 100644 take_screenshots.py diff --git a/assets/screenshots/chalk.png b/assets/screenshots/chalk.png deleted file mode 100644 index 12c2228f5d132b923c49b7c3259092e9bda0bab3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2061 zcmZ`)c~lbU7N^WTwM|?oNk=nHa$(eGPh4<8)C?8Va!GP|JX7f@reSU=PkZK;V~Hq8 znxUB?sM9hoSyq-Lqfjmh`3hvr#8Ht^Lk4HgJMaDT{`kJ{-2408``vrbJ?D1~6@<{y zGS&hB06IuN?-1qNwS6?ylsAm6<^TYwbCKSj=&bs$ItS* zNLm&E<`{na4ok0eu^a=xQWf0)K5ADaKa87guY(F8{ELv+0!Y$ip(MOL!Eavp_TsAZ z&$e09C9%4}+Gu@gbReMHW(FmA^OFa}HenCPXQ&)N8p)f zYF^wnqu;8C&3~T#PMt?C^RR$aC(sp-We;o9C%r|M*689_Otp3F0}-MWMjm?m?ZCA* z2CLok#8h%_^MMtX3rX)CU5%veWk&{E4Sh=vnk&p08;qE+Vy#z&jEt(;gWGG=M1w)K z?1~@G=Q`2XV|yPS1zsAod6s0A2=!pUAo~Kk+dW+;{L5=XMiL6@$Y#+;?v`$x3G+;7 z=Gix`kUL9? z|Aqw&G!*8Qh9i7xH`TuqpQE>Azf?%u zu&eELk8{_j`E6<~c^!o#N`2nfBcb2tgM&k`OVDwqHT1~HZ1qwJ6K?5hKnZKG#hB=2 zZP;qhz|M^Y>LO<$_)k}m&=n+dD}nZ8E})(qaCX`DTR*<)z@q8utg`dE-Jca07Ppkr9wkPE0K#QsPJ;4DCIGbCSWi z5Ft8JuO&y$F*!OO8geU37DtD{`J(hjh%;>P`)yW?Z%#%P6P>~_GuED*V&79#4t`8KsV$yX0LV|G-l(oF?v0JRb>UGyAGR}jAq`@{d4k9< zi|!EaB*-)v_R@kj)!Y0?2sqpAqHc^x@?tfvtz5t19E^J2Ei32{jWw4T8YbdhX1m*HNZ%PVJBG6uDh)oR2+9;<>QaBWRi6k@@sG zMUTAxEh02V%tJs4jcI}&>H_Y&t~~_d?4*FTa%p;WQHHg_hb*S9pao5x9OR=X?9iNw z7jR4AqSGlU%vigjHX2sky&V-H{`_rWYhgQI9IdoByao!=p7F+hCf69TIyq%UzCT4a zoN@%asq;DTNb$gx-wtMZX{XRsR%X*b>Oi`Px+BG-1lfh-gpbfW8 z886A%U0LI5&YI*NFE#gjAc6LB@y8N@FFztoG(O|Y;8eTamGI@!_@D&RUP%l^1ve3e z|!Q ze>UjaRKby)Z@Yt$dyyMX*@Io@YzJD&>j@~(*q;o0MjnH2!g|5*mb z4yVjVEvlu- z-111&Rm`83?G49&q`J{9;=zHi{_H-#cg>`OsDKi#2=1>P3Oi?hVJy(3#KJo%-SiHz zm7-*0OsL})?eCt3d^R#%H?)HSxF0^@HIHRHtQ{Lev%9PHT>}t!%|HrU06E>)##pPi z{$hQvG#0A6YwOJQ>ou4K%V@4fr9pv_PSGNKE!VHELuJCK9z(;#ONyKSzI%Y*xLaH2 zyL5MRm<;e$Z;-*UW3G9PE${wl5`JqL-`P~axo)K4uvUHCY~PZb03sBoQRS1Vovd(` zUMhOs;nmp>{-)XTg=@`89S!Xu`9?v^R1$47#noq-A6RJwNczPCViQ7wRiQ@>hKk1nHCy9VyUum2m~|Awz$_m>)ERO)3K?rQtV zlpDZg8nQCu7nQ7G;0Yt932evlX}Bf)-EHSaV&uH}L#L?cvttlP!}(uv!q|17v4&Jk z9T4rcSvCD|EblN#y>kS_kZk-+ugLl9{ARAr{4>EnHz*=dx5iAcV02qEow+iH9b6{b zC&wVY2)6mbT>ahNrs||g!kFD1xQiCLCpyR QrOX46K0)3c@Yt)r1IxAtNdN!< diff --git a/assets/screenshots/diorite.png b/assets/screenshots/diorite.png deleted file mode 100644 index d477ad4c0ab2e3715844007e2ed0ee4d35446da0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1427 zcmeAS@N?(olHy`uVBq!ia0vp^6M%RH2OE&&&rh#lU|@~%ba4!+nDchl&Ab>z0oLdL z>u+7u5DIz}*>G7q#M7qmrQH`@_jwg^_6$t@Zx}8}voLW&k+jl)3aS` zip_?b;+cOZDOYP&d^KM=#a4y8auMq)1Nq6fiW;9NMxLCk7|{Cj#MjmAA-|Ocm^}Xq zax^aa$I;?Y)Ha*-*OZG(w#6(s(2!PiN9V%oIccR&nOxbnoXTaYEL`j0uT!KnA?m>g z##-jaD@^VDFQhq^h*{J)+;>pedf*}RFE*x?taI3|q@Dl@7f1vwcT}DbrQoq(mHx79 zzs2N6g`Q(=%|T?A4b?-^KRVa zys=7`CCQV!G2)Vw!n7@CSfh^a-dFnn)z3x0`=6IFN4K1pI+q3H8vW`|4?7&y4&>$l zxto6V|Gl|@Bg8m9?Egl4X_3aPXQyA;e@kyx3OHL6`SASm?uWN3e&a!joNU6Q{=;l=G zuxT$U8rPh!wvW$!`%M1#J@HU>nc925e`aNy|G)8l-wLY-FFxNpA0EB?=ka~tU9U2_ z&;MSx@7Are_TTpEui~pv~8R7chaId zk3FALzsR3o)3#Nr=$m)fFU8JN;&X`cFnoL*EZJ!jnZvSOq zf_ff(QtSHt%r1wmpVy{Lef{3#tDN6g@es?~Sz$Z>`31j!ct;^XB$cIW$zq34Pr(=e zk6jEAfAPO(s;98VWIm=+#zp}TCMbTC(ReR*NwY(&ifz~e|LH6B0+!dmyv337bCWe! zh~jm>u$}uH-9AsRZFUG0nks(caq4}gfEE{ykPob(=RxjyFDn2viL1kbiPTbp^;4( Qu&`zDboFyt=akR{0P{Da=l}o! diff --git a/flake.lock b/flake.lock index d02e5fb..dea507e 100644 --- a/flake.lock +++ b/flake.lock @@ -113,6 +113,20 @@ } }, "nixpkgs": { + "locked": { + "lastModified": 1765270179, + "narHash": "sha256-g2a4MhRKu4ymR4xwo+I+auTknXt/+j37Lnf0Mvfl1rE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "677fbe97984e7af3175b6c121f3c39ee5c8d62c9", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_2": { "locked": { "lastModified": 1734649271, "narHash": "sha256-4EVBRhOjMDuGtMaofAIqzJbg4Ql7Ai0PSeuVZTHjyKQ=", @@ -133,24 +147,26 @@ "commit-hooks": "commit-hooks", "flake-compat": "flake-compat_2", "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs_2" }, "locked": { - "dirtyRev": "3fe382c507afd73a2c6a51ece280c3fb567ac53a-dirty", - "dirtyShortRev": "3fe382c-dirty", "lastModified": 1764961369, - "narHash": "sha256-TE0XcWkJNwMVKonZ8y/c4kVLEp71A+45T5Fys2Jv2uI=", - "type": "git", - "url": "file:///home/diomidova/Pebble/pebble.nix" + "narHash": "sha256-FPMMcBAoeQgA/W92XTOAmTdDMmhbpNgsuSia7BMOBUs=", + "owner": "diomidova", + "repo": "pebble.nix", + "rev": "3fe382c507afd73a2c6a51ece280c3fb567ac53a", + "type": "github" }, "original": { - "type": "git", - "url": "file:///home/diomidova/Pebble/pebble.nix" + "owner": "diomidova", + "repo": "pebble.nix", + "type": "github" } }, "root": { "inputs": { "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", "pebble": "pebble" } }, diff --git a/flake.nix b/flake.nix index f00e9b3..901232c 100644 --- a/flake.nix +++ b/flake.nix @@ -8,10 +8,19 @@ }; outputs = - { pebble, flake-utils, ... }: - flake-utils.lib.eachDefaultSystem (system: { + { pebble, flake-utils, nixpkgs, ... }: + flake-utils.lib.eachDefaultSystem (system: + let pkgs = import nixpkgs { + overlays = [ ]; + inherit system; + }; + in + { devShell = pebble.pebbleEnv.${system} { withCoreDevices = true; + packages = [ + pkgs.python312Packages.ipython + ]; }; }); } diff --git a/screenshots/basalt/01_white-black-black.png b/screenshots/basalt/01_white-black-black.png new file mode 100644 index 0000000000000000000000000000000000000000..dbb0773faeb86503033bff3000aa647e9f87167d GIT binary patch literal 1414 zcma)6eN@s{7$ylUm31mDmuqdSoO6j_g=OZ?%4RH7Ohd|#{icmHzouzU(*T`YNJ-Ny z^NY$8Q3|3M1z2Edy8JqtA%(3h!70X4C#8H1bo1Z!$9?a8&hy-J?)%*LeQEeWe}v5% z8wdn~!0z)qVBXJ}7ki17IZ_aB-60TI0M>6;=uZ`IE;SboW9;_mOk`2W4YrKGHXMWX zwa=nd6Rdpi?HMc{P!#pmh$#-mRNC*-mLp*FF}T(%B>7s`6Jce@VG<@xam=~VF5wI4 z%EyILkt;TK2N;xqU3ZM^TSQ_8}Tf={OL!Odq^v6#g5)OXinEievMHnG4 zEkB=`*B*rm_d@>Gp#^g9FY|qBOR8zvd;FX*n@?0G)*i_bh@f!-7$-_cmQ^>Bynm^JtY=Nt zCg=V@y?e{J1!hZt%Uqx<=k4AA?d&ubuRv`+=~Pl;Nh=+!WI@(Y$|DfOk`|hTTX=Hs! zT55knFq2IVL;hvl#whIi)K2-Lq(cmJSI6+J_snD{CpCi5<3_klb!p0z zhv})1P;X_b^qw&I3wK$U^iC(<2d-5D73u(Pk_~kKK+>60QK~T(hUYiM9gJnxl*0us zp3g?cSX8%1XSG6697s>C&fzBAr&N+gL=CrPCAy}b;WaDd{wKKVGETbEXLPd!3MWl0 zRD#ipL@HNHTa3o~u~~Yso-Z3a|6kKClmc8^S7ow0HV~C~*xoSutmf>^w7IsXKKAzBcyXE0et{No}NK$yP;i#asLrIPIFCsX^i7w>ln)*tI7)AFlD*1 z?cd3c%|Q^|^hF&fof-e_O4S0ziuawY$3BaQwCI z*QpZ)i*z%T$kW3nSXpg*_`ij3PU@A_4g=%pfPY&?Hg5UzARtKWqn4;fzU`ZJ2%Gpm zJup?%AoS>2p^Sooqfhab8E-AaqaoKjh+Zj9Ktdl3Bg;FaC}D@n1BEk7^}SSD6y_qJ zMvr!=X0HJiL-CQAf#jLT_D=GXPa-5rhQyY_={=FZZ^5fLP>fd8Ac7pgaI}JLa}dt@ o68gBEWT0?1ZQt5yz&u|e*u8;%+}&XAKf8F<%>V!Z literal 0 HcmV?d00001 diff --git a/screenshots/basalt/02_black-white-gray.png b/screenshots/basalt/02_black-white-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..69e13381de16df949c26b89e2ebc2a006cc228d6 GIT binary patch literal 1222 zcmeAS@N?(olHy`uVBq!ia0vp^6M%RH2NRHN;QgS_z`)Y$>EaktG3V{9z`Q#KJTA5W z7k`1##$ zY8qeFzx91vK6PzZ1MAVcXuhx;cN=3vlWs zR>*8qS;ISjt#-@Xml21i{j(_z5f)1O{rQJmlLcEdi$5=G#++SK6jpBD>gqj9dh2wB z%I2+4y+AA`l^&lPkEgqalC+gazbo0Y(oYvxMw{=GQ50>cq zz3;7JzdjdVd%Nm)%3}}KHUHgICR$JLtc)yQm1&c$74p|yVWG^xq(a$WJzzmwbc?Koi?_Go9H(6)11a(v?x{_bx1JHz(c z^RKMe_Iux$@n&D;SM}pU&tA_CuP@R`+=tF>4rO`m-=})!dikDSkH053w*35c%=}vz zMD2v7wbAuOXSB}pH)b zzCRmMU#FAUU0Zu-&DZID&D+=x3V8osw(oIMrcdxXQOUlT)rX9v(yzzc|2(7UAsNz^`V-tkE@$o z#Z5gVB!%4CS|&cM)EAAtG0)#ce_pz;MKgcmzU6E>l5(UMySLgbmL$4Zgf)8~$=!P8XdLUZ1vN|ZS;IGLX#Wf2a>)la)Baj}>X?<{J zi)h1}KCZAm7R%T1B|cybIM^kgF4lT0yrO5#w4007d*|+3|A8kmcJp$7DeKz!x6BJ( ziJiZ@ZT&aKfYR>gdAGxVGpyKkw0Qg5)wK*EcOUJ%{Y`Y9;_B>gUp$kSzt^^L3p@Sh z;^bp~_rohf3M|X-J~}$nl`&jwhFGNbj8zrce&Gw=&0U}*x?bm5cjOJ{-^z2UTWz=4 z7w^6z#-iKDbN5Zk9nBu=)47NII*K>1WpEaktG3V{A$h_MQ0Ipd!>xbJO&3CyxBhA zp8ocl(7`-!Z@!EAS4!izX`g1TUae=7Xw#p&oAJ3gyYY*9gGt{{6|vdzzj?!OO$Xw> z8<)zK@yjuY8BbTf@%G8f^YQ8%HtcLk*qvO@)LkFg#rS!)H%C-+Tevep)ZW)cC-xnT%`^KN+s+`)*x#yy+`1ILP3xi`ZPl zT)nq$a??(B@BD6_Pkhtv3Cv{MkjA(sk|BGVs=-y>7e&JH*Wdqr9AjT|CMN9p`GY+F zGH%St`kvcYp?fn%?YaMfFQMV{^k1iKx_fn|cfDN#*wy~*n}7ANB@`y8rJX%+%|1kg z-)wc>=R{4(8P94gZ(Pecn83|@qvn7w!!nzAjV9a7T)K#Pdj%3>kOOu=l;*JY+I(6@GW6oDWfsl=XKn`fMR63 z@iXDx{y(t?|MmT`F}Qv^+kV6PiSnG=CdF>}x_+I1x%dH>w9DJBAKVtjv&kJU&k0vx13RwueIUpk>=iH!-+CJ zo6QeQNo)AZD1C($lrETcrjlYIxu0qd(I3>S&U&~K6~!`FlG#XYyQLG zz?Rj9dv0vdKJad~$$p6q%UNKlfcfC2p5#~a*rt6gmJIt|V9-CY=rvPXvRIh7f%N7L zyCA8QF>R%2q_{!eYwgCF2~$>8OWpXd-k#}t%~k-B7cQ~!Y@V?rRx z?uWN7X?%Ol?|#VKA8&J++*YwdEfqU3>nVTg`=0RB8($)U#RP+=tDnm{r-UW|PO|t{ literal 0 HcmV?d00001 diff --git a/screenshots/chalk/01_white-black-black.png b/screenshots/chalk/01_white-black-black.png new file mode 100644 index 0000000000000000000000000000000000000000..63278669f4d7b05345ef1a4326f2c5ceaf598ec2 GIT binary patch literal 1896 zcma)-`8OMA7st`*)ZW%kqZu7W3DFK^tf{3<2qB`OX|&W@TPLEgrJ}>s-ig;1Tf`oW zU9}=@v{b7?tj##143Y_nCAv_r*e3e^0q^_6^E~%+&i6d`e($;G+)NJyR6$ltRzgBT z!5QY{DSo?-j8|t$~pIFCz*rg z{2iK!PqH=l7_OpOEB3GS1-pFZ*e}1~DyVWo>&;_1?lFdPuNSvdHOL&qRVHHmbi&Qe z&oPxtY77tE*9;e67DmnMs$08k?j(tv+;HdB{XS9mE2zSO$H?-4zM6!jGT+}Z zkWT%Hqhe^%P;GQtSUInJW<_oc{R`M-n3g6Q2`~Iem(gQ2NY2q_v7{u2!8c1%i#Lv= zVEpg7O888XWn-AbAMEL@mB&im{Caj)2DP#m?F9s=m&2#s<(SU3r=GD30vsVN2D(N4 z!oton=vE(YqUYRxSM$Rd*)kpKG;!ruZnfh*k!6rw#`Hb_Z~aw~>AC;#C*VNndFDVr za(@|DiRnl(1KCv~x5Sv9N%LYPnSpI{}4X_Dw7OhJub z&45#nDao(Izr60jZ#s8Da|t$$v5q#Ny}b+H+L?SY!hQCGF*HKUgv;p{Kg2WEJuOyR zF29d~KprKJtww%sv7sUFrdltHcKqcNqj00$pC;V;TvV2^@Ix)fzc3N-<~?(-$4V16 z6Kr)4#kR;oRoP|HVd#j^eEt!7@nCG?07CzSVbp8Rrx(@eqlo@PdaVCYqC<BBV zGYoO`Sr;emvNDhV9081i;h8#|yz}*dbKuPA(kj1d0Od$X1-#0;^X9`qL4ePXJPneo zX_|g9FHU3<{9(}qy2Eso7~^576>!lW&G1op3TWA|7dq#nj&SuC zctjMjR0%osEAw)BL4t+R@THYrXiN3R@kKiE@6x8-vrn>m)gP`}<%PEj@4qt?-8|L0 z3Ty45Z|F1$27xW@pMnG)Wc3j?;bc$h*zq1vL+> zI*#lFve<&JH0}$H{-1H3PIOD>)$ITN$Dx0t8g+e2RrGJIX<3jEn`oqORL&egi^k?( zG}z|^HT_V%IJ5BkY31w{Na7w-kJqrdFgYS<>z(yy;vNMf9&GUxQN#c!p!gEz`uU_8$@tP=C+bCf6?1f+gbynd!F)#e~!3qo>ot7Y=o_TK$<9jdJ(Y zO|dUgrc}TK^3fpG0j6>Y;OvhKP5r2##a`WRCTvw)NEZfB~Isi)cv>vgLHa zqe4aBLn)<@ybm@$jOVaJsXbP)Tsh2F>~;`|AqocVy(|JmI9W{kQITeGSS!*?vVYYiyp+gt(#g(_LIiQ=0`;AL4F%pT=dBtZ+ zM?Dd{F)8!hqh#4rTr2s&#c3d0CBjW+#ZM{RqUtkq;8=-)G~E6@A+uhPV)dhyf`uNX zMw|XlCFVwcTn05G1vMV#hCVoPc?@BnuWgVF{1#-bt*ut;L@+G)=AMRkfL@|afn!#~ zd`8*2LVHxamC)Mk4M9s^xOTFSKnbdqd!IWmY vD_&~{MC+=mTkzR<`EaVjEAUhr;80R?lsu>O_L+uwgGxAGK{&NK_@(><=`h08 literal 0 HcmV?d00001 diff --git a/screenshots/chalk/02_black-white-gray.png b/screenshots/chalk/02_black-white-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..bd90cae8fd467268c7ba92ce723c8344216e672c GIT binary patch literal 1351 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD2}o{QKQWboftAnG#WAE}&f8hhlSB-8Sf2lL zzv;~+_($O2jl0`cscg0We0xgVPU!<@o-+gWz<|Qz>r-C6ThO;t^2f)l3CwK@>}L+} z%xIJ}V6jZ#C~~o^h&&QROe!HUk zIXPjk>1UoED%_u{zvr$V@mF%^d(H9S z(D%>1lKsck*=^*WG$@{6bOyTa$CDMGIQvs)JX!IpHaPUVPtg+rweM@JGY?Ok-;z01 z+I`ZSjjP`6Vb86TTW0%CR&(F+RlBD1uJ{yesJro%M`)?ObimW)Nl{5xC$4%GXSU#! z|IsZ+Rw;*G-J9bub$(Z7XQ=qC)!Lf2FC8W3fq2hvuFzidZ!2$Zk=8QRsPOvzc~fQD zA4Dgeyf@MLWTLkVpK80Vpyd>qZ7xp&if#yj1gq~%Tl_P|RA$@p4w<>nS3TUIs?pQk`Rw6u=8Z9w<{M<+5d|%^Xj72pOj}R`rKWU zSMYW5XY2A;2GdpS<+NWPn{IPH{%_FHNn)+VM?Z(2?2U5d3*D!+Gf?})!c*a@=2@(k zAwO3=aa${+d3=7|gu|2mlvw`z)-2=vZcgr$H`AO=ug|fyRH~l6-+a@RQ-4p_`ffY5 z@#BL{TfF)n+*9k{yF~W8R4;Q&rMc%j!+TB?%0Jmq@^0GW!}as~yx^&s8bO+9wRxzdjwVDjn_ER~Z|>PwVE5F0a0m@|`2@w0!d^JPklKe_9_ zRd9d4bAt1RBi8vf$DR3}Xv}zRSXAQ@Z(yeT@l)fH6y7&d#sz9rUzD|{OR#p$%(ri%kM5e^TT_m%(a(lZ*2|t zvrU${HcyfN>Us0DIi8c_|6LGy(!f1|ISo`$@$X=;PhcxLzw7h}e}pLXvclUC>8SMo@# zTAhYX$&;{cbu!YDZ@(>}_n(Hyx{{~fB?BLeN*?(zj+TbVc**n5#(|H)l83zp2R`~r z9`iOhb|WIsct0GQ_z2Gl9Gmz^3dtPDvg6hD5xGHCLgq4x5((a;>L=JC_|1I8=QoBU z)`vX)4Sb}8C&W>!)#=|=R(Rm3?jtcgaFq6un;bH#`WOqZbJQJVEIyms#aI0fFK?~3 z!5faCcJX@s?EP39IIt~+@R+h(keI> z`B=Q}n?E$^Dmc=8tl#70U$pfh!IA4@@djsbm_NbnhGV^qNgTF5)W>j=0gk}!Ir;#H zgN&%5jAVc#d~ZfRQs>OWA&+){91BLxz#-4o97li;`8sa?@Py8$Uku0l;v?UIGJXu6 zv4LVT=--|CtO*YKvXMdGH8|+YMh1P?;Gi!X9Q0))!?At7zX69=TYdA346ks*hvW77n>K7c4*3e` zn~uSOj9ojx2RL?ZaL|_x4*Ig~aEx889o+ZF_kH$Tzv!{Kv{__*h@F|RWsjd8-}kM+ zD2~}LA@XEo#1W5Ue!}}bUO&Dssw5f1KJxYk4lf)7_XP(yzyXeJaF`qg9Bw%Ny_(Na zw!slN*FiWMHz>jJboT%m;AoN&{u4Hdqu~J0!H;bW9AQuU8P{(+L)33t0>^eZ^1=fL zIKTl8a2VqFc#HOv4?F-Im2mvH%go6?-I_O~#c|AsblrTE1;;IpmIenn27Q3zbR1T5 zfdd@i00%g3!^{0h369!0LVTp+7`QJu!f;F`^my`>_XURlN7qkq!vS)ivB0q!N8|O| z&cN5_;OKnJ8XQqCm*Ch9$IQzmICjP{zqbN7KF&F?#0(rCj~%#TaHPL>rs8-#eUt@9 zI*$1z=Ha++aDW3GKd$zw^dG6gu?$DO|78yjaDW3G;5Z6L$R3}fn)T5uW6fOiIAV`o z^;b>K_!yJ1X090=v1jI&)E?2`pf4L7^ksvCzU%-T_}H>zWQ2d9rR6;lXdI4Xd+htS zkXt0r^{M3RF4QyM&(7Z^bFPb$Z@f^0gYJ%P!7EGhT-POEdZAt*%EFK2IcD?W=W23OE1|UCJ@y!f%INj6KA0I9wX$@Sk%uENn=u*SSn2~D zB|1_DI5z8G9F0D};otEx8hr?}0f$nCIgT+O?bnp&>W<^lhyM?5*8vuvHvh>rze?kH z_dFS_e4WbP(h3>(K1$#S2`qM~>@BU60gmvww!(4c103Nv>dCnB0ghN4Rb_nik+(#N zr|LMAGJg9=TB7RtrZf($Qb z>&j{ccLk1I9QPMjr~h2w$i;DWeRb}wWr1T-MlBrb#QRE&V_wD#j@|=IUR<5^V5Q&) z2|gP~*Exr;tj>3~g4ef9hCdEV+P0m zg^w{D2NgcrahzD-Xu)xGf#V7X^;PnC%y3ZOOP-Jo4(g)hIZ1I)4JA)&IS#6`6;=uZ`IE;SboW9;_mOk`2W4YrKGHXMWX zwa=nd6Rdpi?HMc{P!#pmh$#-mRNC*-mLp*FF}T(%B>7s`6Jce@VG<@xam=~VF5wI4 z%EyILkt;TK2N;xqU3ZM^TSQ_8}Tf={OL!Odq^v6#g5)OXinEievMHnG4 zEkB=`*B*rm_d@>Gp#^g9FY|qBOR8zvd;FX*n@?0G)*i_bh@f!-7$-_cmQ^>Bynm^JtY=Nt zCg=V@y?e{J1!hZt%Uqx<=k4AA?d&ubuRv`+=~Pl;Nh=+!WI@(Y$|DfOk`|hTTX=Hs! zT55knFq2IVL;hvl#whIi)K2-Lq(cmJSI6+J_snD{CpCi5<3_klb!p0z zhv})1P;X_b^qw&I3wK$U^iC(<2d-5D73u(Pk_~kKK+>60QK~T(hUYiM9gJnxl*0us zp3g?cSX8%1XSG6697s>C&fzBAr&N+gL=CrPCAy}b;WaDd{wKKVGETbEXLPd!3MWl0 zRD#ipL@HNHTa3o~u~~Yso-Z3a|6kKClmc8^S7ow0HV~C~*xoSutmf>^w7IsXKKAzBcyXE0et{No}NK$yP;i#asLrIPIFCsX^i7w>ln)*tI7)AFlD*1 z?cd3c%|Q^|^hF&fof-e_O4S0ziuawY$3BaQwCI z*QpZ)i*z%T$kW3nSXpg*_`ij3PU@A_4g=%pfPY&?Hg5UzARtKWqn4;fzU`ZJ2%Gpm zJup?%AoS>2p^Sooqfhab8E-AaqaoKjh+Zj9Ktdl3Bg;FaC}D@n1BEk7^}SSD6y_qJ zMvr!=X0HJiL-CQAf#jLT_D=GXPa-5rhQyY_={=FZZ^5fLP>fd8Ac7pgaI}JLa}dt@ o68gBEWT0?1ZQt5yz&u|e*u8;%+}&XAKf8F<%>V!Z literal 0 HcmV?d00001 diff --git a/screenshots/diorite/02_black-white-gray.png b/screenshots/diorite/02_black-white-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..4f969cc7869c0205c06eb1a8574a4e5d0a4eca5f GIT binary patch literal 1348 zcmV-K1-tr*P)Jn@<~ z0OP(5JYY4&?nU35fC*S>30OZ-OEm^onKAVh3P5&&b|~dc%5~_a;gLDNF7w}K9TC3T1o;KV?3fcuiJiFuNr^Zp_)JK zAAgSnqwh_?1ni^)Ou#S$p!@|4-;2960b}$cZcM;h^!lfV6%(*##RRNbF#&7VO~9Jf zO9QK1>YE0Sj_4zRJxrn{Ns=V7q(4hKNq_!_^>-sWtDU0N z?-Z?mr1F1n8d2u0`Sa^T<^1dPTKAvdTUVl$AK28NvCVWZh`)6M zrD&@VFvFj>O*@z8AHRXiMtxzn|C5>3X{9gh&Od$wm#r@>=kI%lPSqEd^N-)aW$O#e z`TL%sQ`ujb|7luZBenU$obUdfbCj9i-;=&5gI3Wm4D$PxKVo`w>Y2-(D$&cYxwA9d znBJew>$Z4jk=C@Ab7R+;f8O_}Mu9z&mcc9(;hcGV)0rIwHgqn?3_^>&H{Y|h;GMMY zoL729nMM8cy`0(6;Gy$QW{bT-wAgzKw@L)>rvd$-+!7ub@S`47sPz%?|XJ}2`zNk%J5n7ch0bw=;>wu ztVeSq^BeDL(Rz2SLUQ^~@1R20d)ekgf8Vof_g(olI;MkrNzf9oW59B>1WdrX>C|cjEU8o55wN5VZc4y1I=ie>z#6{+ zNA|TcA>5ErifCRR*bDkkQyY45m(~IpQ0!jxy$P6rm6m`tlYq^gVY4D6U@lwOxXThS zj4iTKYOpT;g@7Sj#Ru!+UkezrSa7f|{sIQhrS~E&G-``4796aLzkq>r>Agq`joN}+ z#Ru!+UkDhiQfja+{`wDR0lPTEW<^NAnn}Q#Nx+&(!1{?=O28pIEn3$cEfc2Ar^^<5xk|arzgwbyYDo#@6lELi&0000GetBounds(); + // LOG("Digit layer update. %d digits", this->digitCount); ctx.SetCompositingMode(GCompOpSet); for (int i = 0; i <= this->digitCount + 2 * this->extraDigits; i++) { Pebble::GRect rect(0, i * this->digitHeight, bounds.size.w, this->digitHeight); uint16_t digit = ((i - this->extraDigits) % this->digitCount + this->digitCount) % this->digitCount % 10; + // LOG("Digit %d -> %d", i - this->extraDigits, digit); draw_digit(ctx, rect, digit); } } @@ -46,6 +48,7 @@ int16_t DigitLayer::ComputeOffset(uint16_t digit) { } void DigitLayer::RotateTo(uint16_t digit, bool animate) { + // LOG("Digit %d, out of %d", digit, innerLayer.digitCount); digit %= innerLayer.digitCount; auto currentOffset = this->scrollLayer.GetContentOffset(); if (digit == 0 && currentOffset.y <= ComputeOffset(this->innerLayer.digitCount / 2)) { diff --git a/src/c/digit_layer.hpp b/src/c/digit_layer.hpp index d3d3a32..82c68bd 100644 --- a/src/c/digit_layer.hpp +++ b/src/c/digit_layer.hpp @@ -9,11 +9,6 @@ class DigitLayerInner : public Pebble::CustomLayer { DigitLayerInner() : Pebble::CustomLayer(Pebble::GRect()) {} - void SetDigitCount(uint16_t cnt = 10) { - this->digitCount = cnt; - this->MarkDirty(); - } - static void DrawDigit(const Pebble::GContext& ctx, const Pebble::GRect& bounds, const uint16_t digit); friend class DigitLayer; @@ -29,8 +24,10 @@ public: DigitLayer(); void SetDigitCount(uint16_t cnt = 10) { - this->innerLayer.SetDigitCount(cnt); - this->MarkDirty(); + if (this->innerLayer.digitCount != cnt) { + this->innerLayer.digitCount = cnt; + this->UpdateLayout(); + } } void UpdateLayout(); void RotateTo(uint16_t digit, bool animate=true); diff --git a/src/c/main.cpp b/src/c/main.cpp index e55c761..2ae0a86 100644 --- a/src/c/main.cpp +++ b/src/c/main.cpp @@ -7,7 +7,8 @@ using namespace Pebble; -#undef DEBUG +// For debugging +const bool USE_SECONDS_INSTEAD_OF_MINUTES = false; class MainWindow : public AppWindow, public TickTimer { DigitLayer digitLayers[4]; @@ -22,10 +23,6 @@ protected: digitLayers[1].SetFrame(Pebble::GRect(w2-36, 0, 32, h)); digitLayers[2].SetFrame(Pebble::GRect(w2+4, 0, 32, h)); digitLayers[3].SetFrame(Pebble::GRect(w2+36, 0, 32, h)); - digitLayers[0].SetDigitCount(clock_is_24h_style() ? 3 : 2); - digitLayers[1].SetDigitCount(clock_is_24h_style() ? 24 : 12); - digitLayers[2].SetDigitCount(6); - digitLayers[3].SetDigitCount(10); for (size_t i = 0; i < 4; i++) { this->digitLayers[i].UpdateLayout(); this->AddChild(this->digitLayers[i]); @@ -36,23 +33,25 @@ protected: this->frameLayer.SetCompositingMode(GCompOpSet); this->AddChild(this->frameLayer); -#ifdef DEBUG - TickTimerStart(SECOND_UNIT); -#else - TickTimerStart(MINUTE_UNIT); -#endif + // MINUTE_UNIT doesn't seem to be called if only the hours change + // This can happen when time zone changes or in tests + // So we also update time on HOUR_UNIT + TickTimerStart(HOUR_UNIT); + TickTimerStart(USE_SECONDS_INSTEAD_OF_MINUTES ? SECOND_UNIT : MINUTE_UNIT); UpdateTime(false); } void UpdateTime(bool animate=true) { - DateTime date = DateTime::Now(); - int hour = date.GetHour(); -#ifdef DEBUG - int minute = date.GetSecond(); -#else - int minute = date.GetMinute(); -#endif - if (!clock_is_24h_style()) hour %= 12; + DateTime dateTime = DateTime::Now(); + int hour = dateTime.GetHour(); + int minute = USE_SECONDS_INSTEAD_OF_MINUTES ? dateTime.GetSecond() : dateTime.GetMinute(); + bool is_24h = clock_is_24h_style(); + if (!is_24h) hour %= 12; + + digitLayers[0].SetDigitCount(is_24h ? 3 : 2); + digitLayers[1].SetDigitCount(is_24h ? 24 : 12); + digitLayers[2].SetDigitCount(6); + digitLayers[3].SetDigitCount(10); this->digitLayers[0].RotateTo(hour / 10, animate); this->digitLayers[1].RotateTo(hour, animate); this->digitLayers[2].RotateTo(minute / 10, animate); @@ -66,7 +65,6 @@ protected: namespace { void ApplySettings() { - Pebble::Window window = window_stack_get_top_window(); window.SetBackgroundColor(settings::GetBackgroundColor()); window.MarkDirty(); diff --git a/src/c/settings.cpp b/src/c/settings.cpp index 08eabb1..1bccebb 100644 --- a/src/c/settings.cpp +++ b/src/c/settings.cpp @@ -31,14 +31,13 @@ namespace settings { } void HandleMsg(DictionaryIterator *iter) { - if (auto tuple = dict_find(iter, MESSAGE_KEY_BACKGROUND_COLOR)) backgroundColor = GColorFromHEX(tuple->value->int32); if (auto tuple = dict_find(iter, MESSAGE_KEY_DIGIT_COLOR)) digitColor = GColorFromHEX(tuple->value->int32); if (auto tuple = dict_find(iter, MESSAGE_KEY_FRAME_COLOR)) frameColor = GColorFromHEX(tuple->value->int32); Save(); } - GColor GetBackgroundColor() {return backgroundColor; } - GColor GetDigitColor() {return digitColor; } - GColor GetFrameColor() {return frameColor; } + GColor GetBackgroundColor() {return backgroundColor;} + GColor GetDigitColor() {return digitColor;} + GColor GetFrameColor() {return frameColor;} } \ No newline at end of file diff --git a/take_screenshots.py b/take_screenshots.py new file mode 100644 index 0000000..ccfe0c7 --- /dev/null +++ b/take_screenshots.py @@ -0,0 +1,141 @@ +# A simple script to automatically take app screenshots +# Hopefully some day it'll grow into an actual testing framework + +from uuid import UUID +from datetime import datetime, timezone +from time import sleep +import os +import png +import json + +from pebble_tool.util.logs import PebbleLogPrinter +from pebble_tool.sdk.emulator import ManagedEmulatorTransport +from pebble_tool.commands.emucontrol import send_data_to_qemu +from libpebble2.communication import PebbleConnection +from libpebble2.communication.transports.qemu.protocol import QemuButton, QemuTimeFormat +from libpebble2.services.install import AppInstaller +from libpebble2.services.appmessage import AppMessageService, Uint32 +from libpebble2.services.screenshot import Screenshot +from libpebble2.protocol.system import TimeMessage, SetUTC + +package_json = None +with open('package.json', 'r') as file: + package_json = json.load(file) + +app_uuid = UUID(package_json['pebble']['uuid']) +appname = package_json['name'] +target_platforms = package_json['pebble']['targetPlatforms'] +msg_keys = { + key: 10000 + i + for i, key in enumerate(package_json['pebble']['messageKeys']) +} + +def emulator(platform): + print(f'Launching `{platform}` emulator') + pebble = PebbleConnection(ManagedEmulatorTransport(platform)) + pebble.connect() + pebble.run_async() + print(f'Installing `{appname}.pbw`') + AppInstaller(pebble, f'./build/{appname}.pbw').install() + sleep(1) + return pebble + +def for_all_platforms(fn, logs=True): + for platform in target_platforms: + pebble = emulator(platform) + if logs: + logger = PebbleLogPrinter(pebble) + fn(pebble) + logger.stop() + else: + fn(pebble) + + +def is_color(pebble): + return pebble.watch_platform in ['basalt', 'chalk', 'emery'] + +def send_app_message(pebble, msg): + ams = AppMessageService(pebble) + tid = ams.send_message(app_uuid, msg) + + # unfortunately the following doesn't work + # wait_for_event assumes only one value is returned + # but ack returns 2 :( + + # tid2, uuid = ams.wait_for_event('ack') + # assert uuid == app_uuid + # assert tid2 == tid + +def set_time(pebble, hour, minute, year=2013, month=1, day=23, tzinfo=timezone.utc): + dt = int(datetime(year, month, day, hour, minute, tzinfo=tzinfo).timestamp()) + pebble.send_packet(TimeMessage(message=SetUTC(unix_time=dt, utc_offset=0, tz_name="UTC"))) + +def press_buttons(pebble, buttons, duration=0.1): + send_data_to_qemu(pebble.transport, QemuButton(state=buttons)) + sleep(duration) + send_data_to_qemu(pebble.transport, QemuButton(state=0)) + sleep(0.1) + +def press_back(pebble, duration=0.1): + press_buttons(pebble, QemuButton.Button.Back, duration) +def press_up(pebble, duration=0.1): + press_buttons(pebble, QemuButton.Button.Up, duration) +def press_select(pebble, duration=0.1): + press_buttons(pebble, QemuButton.Button.Select, duration) +def press_down(pebble, duration=0.1): + press_buttons(pebble, QemuButton.Button.Down, duration) + +def set_24_hour_mode(pebble, is_24_hour=True): + send_data_to_qemu(pebble.transport, QemuTimeFormat(is_24_hour=is_24_hour)) + +def screenshot(pebble, name): + filename = f'{pebble.watch_platform}/{name}.png' + path = './screenshots/' + filename + print(f'Taking screenshot `{filename}`') + os.makedirs(os.path.dirname(path), exist_ok=True) + image = Screenshot(pebble).grab_image() + png.from_array(image, 'RGB').save(path) + +# ============================================================ +# Code above this line is not specific to the watchface and +# should probably be eventually split off into its own library +# ============================================================ + +def set_colors(pebble, background, digits, frame): + def wrap_color(color): + if isinstance(color, int): + color = hex(color) + color = color.removeprefix('0x').removeprefix('#') + if len(color) == 3: + r, g, b = color + color = r + r + g + g + b + b + return Uint32(int(color, 16)) + send_app_message(pebble, { + msg_keys["BACKGROUND_COLOR"]: wrap_color(background), + msg_keys["DIGIT_COLOR"]: wrap_color(digits), + msg_keys["FRAME_COLOR"]: wrap_color(frame), + }) + +def run(pebble): + set_24_hour_mode(pebble, True) + set_time(pebble, 12, 34) + set_colors(pebble, 'FFF', '000', '000') + sleep(1.25) + screenshot(pebble, '01_white-black-black') + + set_24_hour_mode(pebble, False) + set_time(pebble, 16, 59) + set_colors(pebble, '000', 'FFF', 'AAA') + sleep(1.25) + screenshot(pebble, '02_black-white-gray') + + if is_color(pebble): + set_24_hour_mode(pebble, True) + set_time(pebble, 4, 20) + set_colors(pebble, 'FF5', '00F', '00A') + sleep(1.25) + screenshot(pebble, '03_yellow-blue-blue') + + +if __name__ == '__main__': + for_all_platforms(run) \ No newline at end of file