diff --git a/CHANGELOG.md b/CHANGELOG.md index 476adee..b8c04ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - Support for custom BMP icons for games and folders - by @tasken - Support for custom NDS banners (custom titles, subtitles and animated icons) for games and folders - by @tasken +- Theme selector ### Fixed - Top screen cover is now displayed/hidden correctly when placed partially or fully off-screen diff --git a/_pico/themes/raspberry/icon.bmp b/_pico/themes/raspberry/icon.bmp new file mode 100644 index 0000000..2da8301 Binary files /dev/null and b/_pico/themes/raspberry/icon.bmp differ diff --git a/_pico/themes/raspberry/preview.bin b/_pico/themes/raspberry/preview.bin new file mode 100644 index 0000000..c6da440 --- /dev/null +++ b/_pico/themes/raspberry/preview.bin @@ -0,0 +1,20 @@ +ĜĠĜĠĠĜĜĠĜŠĠŠŠŠŠ&G'HHHHHHH(G''&''hIjjjijiiH'&HijijiHh'&&'&&'''ĠĜĠĜĠĜĠŠ&&&'&&&&&&&''&''&''&'&&&&&&&&'&''ĜĜĠĜĠĠĠĜĜĠŠĜĜĠŠĠĠŠ&'(HHHHIHHG(''&&'GHijjjiH'&HIkjhH&''&&&&'&&'&ĜŜĜ&&&&&'&'&&&&&&&&''&''''&''&&&&'&&&&&'''&&''''&ĠĠĜĠĠĠŠŠĠ''HHHHHHHHHHG'&'GGIhjjjHH&'hikkjh'&'''''''''&&&&&'&'&&'&&&'&''&&&&&'&&'G'&'''&'&'''&'&'&'&'&''&&'''G'ĜĠŠĠĠŠ'(HHHHHHIHHHH''&''GHIijiihG'&&Fii'&&&'''''&&&&'&&&&'&'&&&&&&'&&'''&'&''&&&&'FGG&''&&'''''G''''GG'G&G''&''&'&&&'G&''&'G''''HGGG&ĠĠĠŠ&(hHHhIHHHIHHH&&&''(GHhiiiiiii('''&'hjF&&&&&&&&'&&&''&''&''&''&&&&&&&&&'&'''&'&&&&&&''G'&''F&'G&''GG'HGGGGGGG''''&''F&'G'(G'G'GGGGGHHHHGŠ&'GHhIIiiIihiiGG&'''HHIIHIiiiiihHHG'G'GHh&&&&&&&&&&&''&'F'''GG'GG''&'&&&'&&&%&%&&&'&&''&'&&''&'&''&'''GH(GG''GF'G'GG(GGHGGGGGGG'GGGF'''&GGGG'GGGGHGHHhHHH&%&&&&&'GHiiiiiiiiiIhG''''H(HiIiiiiiiHHIHGHG'Gg̹G&&'G'&&&&&'G&'G'G'GGGG'GG'GG'''&'&&&&&&&&'&&'&''&&'''G''FG&G''GGGGGGHGGGG'GGGG'GGHGHHGHHGGGG'GGG&GGGGHGHGGGGGhHhhihh&%&&&&&&&&&&&'&&&GGhhiiiiiihHGGGHHIIIjiijjjjjihiHGHHG'hg&G'G'GFGGG'GGGGGHGhhGGGGGG'GG&'F'&&&&&&&&&&'G&&G'G'G'GG'GGGFGGGGGGGGGhghHHGGHGGGGGGHGHGGHhHgGHGGG'GGGGGGHHGHhGHHHgGhiihiH'&&&&&&&&&'&&'&&&&&'&&GGhiiijiih'GHHHIIIjjjiiijihHHGHG'HhhhG&FhFFGGGHGGHhGgHhgGHHHhGGGHGGG''&'&&'&&&&F&%&&&&&&'G''GGGGGGGGGGGGG'GHGGGGHhhHhghHGHHHghGhghGhggHhGGGGhGGGGFGGhHhHhhghhhhihHG&&'&&'&&&G&&&'&FG'F''F'GGHhihHHHHIIJijjjjjjiiIIiihGhGGGGFFGGGGGgGgHHghhHhhhhhhhhhHhgHHGGGGGG'GGFG&&&&&&&&&'GG'GGGGGGgGHhGhGGgGgHgghghhhhHhghhhhhhghhghhhhhGhGhGHGhgGGGGhghhhhhhhhhhHGG'%&&&&&&&&&&&&&&&&''F'&G''GGGGG&G'GF'FGGhhhhHhIIIJjJkJkkjjjJjjiiihhhhhhghggGhghHhhhhhhhhhhihhhhhhhhghHhHGGGGGGGG&''F&&&&F'GGGGGGgHhGhhhhhhHhHhhgHhhHhhhhhhhhhhhhhhhhhhhhhhhhhghhhgGHhGhHhhhhiii%%&&&&&&&&&'&&&&&&'&&&&&&F'&'FGGGGGGGGGGGGGGGGGGHghihIiiJJjKjkjkkJkkjjjijiiihhhhhhgh˽˹˽˹hghhhhhhhiiiiihhhgghGhGGGhGgGG&&G&G''&GGgghHghhhhhhghhhhghhhghhhihhhhihihhhhhhHhhhhhhghghhghhh&&&&%%&&&&&&&&'&'&&&&'&'&&&'F&'&&G'GGFG'GGGGHGGHGgGHGGgGGgghiiIjjjjjkjkkkKjkjijiiihhg˽˹˽˽˽˽ghhhhhhhghgHGhGgGGGGGGGGGGHghhghhhhhhhhhhhhhhhhhhhhghhhhghhhhh&&%&&&&&&&&&&&&&&'&'&G&&''&'G'&&''&G&&GF'G'GGGGGGHgGgGGhgGgghhhhjjjjkkkkkjhʽ˽ʽhhihhhhhhGhHGgGGGgGHgHghhihhiihhhhh&&&&&&&&&&&&&&&&&&&&&&&%&&&&F&F'FGF'GGGGGGGGGFG'FGGGGGGGGgHGghghGhghh˽˽˽ʽʽʽʽʽʽʽʽjhhhhhhhghghhgHhghghh˽&&F&&F&&&&&&&&&&&&&&&&&F&&&'G''GGGGGFGGGGGGGGGGGGGGGGhGhGhghghhghh˽˽̽˽ʽʽʽ˽˽˽˽˽ ˽ʽ˽˽ʽɽʽʽʽʽʽʽʽʽʽʽʽʽʽɽhhhhhhhhhhʽGFGFF''F&FF'&&F'&&FF'&&F'FGFGGGGGGGGGGgGgHgGggGgHgggghGhhhghhhʽʽ˽./ͽ˽ ........ ˽ʽʽʽ˽ʽʽʽʽʽ˽ʽ˽˽ʽʽ˽˽˽ʽʽʽighhhʽʽʽʽʽ ʽG''GG'FGG&GFG&FFGGFGF'GFGG'GFGGgGggGhghhHghhghghggghgghhhhhhh/QQqQQ0нϽν./OOPPPPPO0//0/0////˽˽˽˽̽̽˽ʽʽɽɽʽʽʽʽʽʽʽʽʽʽʽɽʽʽʽʽʽʽʽʽʽʽʽʽʽɽʽ - -. ɽɽʽGGFGFFGGGGFGGFGGGF'GGhGGGgGgHGGgHhhhhhghghghhghhhhhhh /QQrrsQ1нpPOO./0qqQqQQ0000000000/0/˽˽ ʽʽ ʽʽʽʽʽʽʽʽɽʽʽʽɽʽ .- - .-ʽɽʽɽʽʽɽɽʽɽʽ GGgGGGGGFgGGGgGFFGGGgGgghghghgghhhhhhghhh ./PQQRΓғғsRʱQ0/00Q1qrrrrQ1 -..M...-, NOOO. ʽɽʽ N.N..N-Nʽʽɽʽɽɽ gGgHgggggFGGgGgGgGgGhghhggghhhhhh .OQRsRrsғҔ֓sʑQP12rsrRQRRRR1qQqq, ʽ .-..N..N..-NoOoOoN ʽʽʽ ON.NNN.N--gghgggGhgghGGGgggGgggghhhh .OQrsssRRsғ֓3rQq1SΔ֔֔֓sR1rrrR1ŰqQ11Qp ,.NONONONONOnpppppOpN ONoNNNNo-,FGhhgghgggggghhgghghh NOqss֓t֓sRRSs212sҴڴ֔֔֓s22rrғsrrqrrrP0/0ő1Ѩ1r ,--OOOoOOnOOOOpҐҐpҐpppo--,-- ooOoonOo, hhhghghghhg .Ors֓֔֔֔ڔtsœ32sҕڔִڔ֓S2SSrsrRrrrqQQ0Qғֳ֓r1ɲr򨒠QQ01q2q , --,--Ooooooopooooΐ֑֐֑֑֐Ґ֐p--MM--, + + MΐooooҐN Qνhhhňhh-OQr֓֔ڔִ֕֔֔T3ɴ33Tt֔֔tS33S3rSSR222ŒqγڳRS򨑜Q211RqR0- - - , + ,,-,--M-noҏopҐҐp֏Ґ֐oΏpڑ֑֑֑֐ґ֐NMNMMM-,,,,,,,, , , , , , ,, ,, , , , ,oҐ֐ppo, ʴ0ƫũ .1RssҔڔ֕ڵڔ֔T4ɵŔ4TTTtT334SST3ųsrRQrɔړRɳS󨓠Q2R2RrR21/.N.M.----M--MMMNNNnҐp֐֐֐Ґ֐Ґ֐֑֐p֐ֱڱڑֱֱֱNMnNnnnMM--,M-no,-M,M-M--M---M,----,---,,-, ,,, , , ,,,,,, -nN,, , , ++ ,ʳګh /1SST֔u֕uuU5ɵuUtTtT444T4ΓT3333r3tڳڴڴڴڴޓSsŴœsRRrrr򬓽212QPNONNNNNNNNMNnnnNnҐ֐֑֐ְֱ֑֑֐ְ֐֐֐֐ڳޱڐnNnnnnnNMMMMMҏґooMMNNNMMMMMMMMMM-M-MML--M----,,,,,,,,,,,-,,,,,,+,, ,,, ,,,, , , ,,,,,,,,,,,,G 0455555ɵu5UUT44T4T4TssRs֔ڴ޴ړRRS3s3RsŔ3Ҩ33RRRrqOoOOnOnnonno֎noְְֱ֑ڱڱڱڱڱڱֱڱڰ֑֐ڏ֏֏֏noo֎o֏oonnNnMmnҐڐnnnNmNnNMnMnMNMMNMMNMMMMMM-MMLM---,,MMM,-,-,---,,,,,, ,,,,,,,,,,,,+,,,,,,,,,,,Ωũ-/2Ŷv65vu54ɔ44ts3SsS2ɓs3󬳤ӬTɵŔssSt5tsr֓֒֓ڒڑ֑֑ڐڱڑڑڱڰڏ֏o֏֑ڰڱڲڱڱڲڱڱڱڱڱڰڏ֏ڐ֏֐ڏ֏o֏ڏ֏֏onnno֎nnnҏo֏nonn֎nNnNnnNnnnNnMNnmMNMMNMMMMMMMMMMMMMMLMMMLM,,,,,-,L-L-,---,M,L,LLMMM,MLMũ P2ŶŶŶŶŷŷŶvVvv5ɵŴu4ԬԬ343TsT4ӤssststŵŔŴŴ5ҕڵ޴޴޲ڲڒ޲޲ڲ޲ޱڑگڏڰڱ޲ڲސڏگڏ֐ڏ֏ڐڰڰڐڐڏڏoo֏no֏ڏ֏֏ڐڏڏ֏֏ڏo֏֎o֎n֎nnnnnnonNnnnnnnmMMNMNMMMMMmMMMMMMMMMMLMMMMMMLMMMLL-MMMMMLMMLmMMM O176ŶŶŶŷŷW666w6ɵuu͕UԨԨԨԬԨTS34334SԬTttuTҔڔڕttږڵޱޱްڰڰސڰڰڰޯڰڐڰڰڐڏڏ֏ڏڏڏڐڰڰްڏڐڐڏگڐڏڐڏڏڏ֏ڏn֏ڏ֏ڎon֏nڎnnnnNmnnmNnNnmnMnnMmnMMMMMLMMMMMMMMMMMMMMMMMMMmmmnnnmN + P3WwW7ŷŗwŖw6vWɕuUuɕuUլtttu44STԨ5UT788޵޴޵޴ްްްڰޯްްڰްڰްޏگڐگڐڰްްڰޱްްڰްްްްްްڐگڰگڏڏڏڏ֏ڏ֏ڏn֏n֏nn֎nnnnnnnmnmnnnnnmNmmmmMmmMMmmmMmmmmMnmmmnMnnnnmnn֎n + + + + Os6W֘ژڸx8ɗwWwŘw687vuɖ766Ε5ըvuUT4444433tըsU֔8YX8UV5Uv޴ޱްޱްޱޱްްڰްްްޱޱޱްޱްްްگޯگڐڏڏڏڏگڏڏ֏ڏڏڎڎڎnnnnoonnnڎnnnnnnnmnmnmmnmnnmmnnnmnnnn֎oڎ֏n֏ڏڏڏn + + , + + + + MqtVɶXXɷxWWwww7Ͷv6җw7W֗ژwVV5554887sssu7ɶŖWuڵޱްްްްޱޱްްޯްްޯڰޯڏڏگޏڏڏڏڏnonoڎ֎֎ڎoڎoڏnnڎnڎn֎nnnmnnnn֎nnnnnnnnڍ֎n֏ڎڏޏگڏڏڏڏڏ + + +,,+,,,+,, o֔uW͗Ŷx9y͸wxXXwXxvɸ9җwWζ6֬֬VV654tu443X8ޔut5Uږ6W76vV֖޵ްޯްޯڰްޯޯޏگޏڏڏޏڏޯڏڏڏڏڏڎڎڏnڎڎڏnn֎nnnڎnnnnڎڎڎnڎnڏڎڎڎڎnڏޏޏگްޯڰްްޯް + ++,,+,,,,,,,,,, ,, oruw8wŘ:::YɘxxXXX8x͸vW:ɗV6լըTU5453T54tYy8TTUtuuUuuVڶ6u֤֨֨֨֨Vwڵްްްްޯްޯگޯޏگڏگޏޯގڏڏڎڏڏڎڎoڏڎڎڎnڎڎڎoڎڎڎnڎڏޏڎڎڎڎޏڏڎڏޯޯްްްްޱޱްޱޱ + + + ,,,-L,-L,,L+,+,+L,,+, + , + Nqڕwx8ҘWɹ:Z9ҸxxxXX8XŸɷwxvvwWW6v6WwږږޖvUUԨt4Utv5544X7tT͵U55uvږ66vVVvvWږްްޯްްްޯޏޏڏڏڏڏޏگޏڏގڏڎڎڏڏڎڏޏޏڎڎڏڏڎڏގڎڏޏڏޏڏޏڏޯޯްްްްްޱ ,,LLLlMLLMMm3LL,L,,,,, ,, ,,+ .qtޗx8xWəZ:yxxXXX8ŸwxҷW76Ŗ9:9:99:85UըV555U4uڳŔ6uޕV5ԬWWvV6VvVWްްޯްޯްޯޯޯޏޏޯޏޏޏޏޯޏޏޏޏޏޯޯޏޏޏޯޏޯޏޏޯޏޯޯް ,+,,,lMMMMMMlMMگwv3mLML-,L,+ ,, , ,osޗwxҸXXYXֹyxX9ٰذw8x8wvZ{{99:9Vu5uuWv5uڶҕ5լԨu7Η77767Vw׬W͗ް5Vްްޯޯްޯޏޯޯޯޯޏޏޏޯޏޏޏޯޏޯޯޯޯޯޯޯް,+ ,LLmMMmMmLmnmmwLMMLL,,L,,,,,+,Mqޕww8xXYxyڙyљx98ٰyy8w͗W76:{{{9Wڗޘxv6Vڗ޸޶55vޕޖvVհԬVͷ7776wרw73xx7ްްޯޯޯޯޯޯޯޏޯޯޯޯޯޏޯްް++,,LlMMMmmmmMmnmMLmڎڏگnlMMMLL,LL,L,,, oޓwwYљYXYy͙yx8Yx88XW7V79{z9xV֗޸w޸w6֬6Vwxڹ֖VWޗޖޗv6͕5utuլW7פW777Wwx343443mڰްްްޯްޯްްޯޯްޯް,,+LMMmmMmmmmnmmmmmmmmnMmMLML,,L,,,,L+,puޗX9͙X9YyyYxyřřXYججYX8װ֬67:Y9WwژWVwVXy77V76V޵u5͵ŕuuTTU6wWרV8777w7η33434xްްޯޯޯް,K-LmmMmmmmmmnmnmnmmnmmmmMLLMML,L,M,,,MqޖwYY8YYYx89YřXYٰجXYyX֬7:xxxwޘwV6WvvWwwwv֬vҙW765v7xyYv5U4tT4TT77רV6766xڴ343443yްްޯޯްޯޯް޶޷޶,,LmmMmmmmnmnnnnmmnmmmnmnMMmLLM-L,LL,,nrޖxX͸y99XXYXXYyجX8ٰYY8հθxxWXW6wװVV6666VvVvVWyXXXU֕UtT43U7׬W67676VWΗ3333333yްްޯް޷,LMmMmmmmnmnnnnmnmmnnMnnmmMMMLMMMML,++nړޗxXѸY99YYY8Yx9جx88yYŗޘxw67ҷw7wV6666566VU6VVרV7֖vɵVڕ֕TհԬxְլTS4v666666X3334433ޯްް޷޷޸޷,LmmmmnmnnmmmmmnnnmnmnmnnmLMMML,ML-,,,oڔޗx9͹y89889Y8X7xY86Wޗޘ͘W7w7vVVUV6655655vVu֬װְլWӨְըtS4666833334333333ްޗ޷ޗ޷,LmMmmmmmnnnnmnnnmnnnnnmmmmMLMMM,LL+,LoڕޗxYy89جبx87٬X9Θxޘޘޙ͘7WW7V֨vvvUVU554vuդuUuuTTwsլըT3u֨6W׬vV֬wx4434433޸޷ޘ޷޸LLMmnmnmnnmnmnڍnnmnmmnmnmMmMMLLM-M,,+Lpޖx9ə9جججwX78x8W7ֹwxڹɷ7wWvW6׬vvuU565555tvuUUu655U5T3STըըS44vVwWŷY֙343433޷޷ޗLMmmmmmmmnnnmnnnnnmnmnmmnmMLMmMLLM,,+M֒ޕޘy9ə9٬جججwX787xxxޘޘwڷŸwV7wwv֬֬vVvu55544UuU55uV5U5T43R7Β34tըt334VW8y8xX8Y֘3333333337޸ޗޘ޷,LmmmmmmnmnmnmmmmmmnNmnMnMMMmLMMMLL+,ҐޓޗyYəY٬٬wXW7777͘޸xxW7͗ŘWvW͗ŖV֬vuT45TTU555TuըT33RT33TԠS3uuɖ8y޷޸Xy433433ޕuږ޷޸LMmmnmnmnmnnnnnnnnnnmmnڍmmMMMLMMLM,,nڒ޶y9ͺy9٬wWW77͸X8wVјw6ɖŗV7֬vU4UTUVVVԨr323334s43UUvT5UwwޗwxW33433333t5VW֖ڶޕޘMLmmnmmmnnmnmnmnnnmnnnmnmMMMMMmMML,Mڱy9y8www777ιxXWVwڷw8ژ8ɷvw7֬װ֤֨45455tTStXWW22334T3TլutU5445tVvww7W3343443uuU5V5V55v޵޷MMLmnmnmnnnmnnnnnnmnmmnnmMMMMMMMMLM֐x9͙y8٬wWW776wŘy8XvYZw7xX7͗W66666դu4TUӤⳠ323TլլԬԬ5tVwwW7Ww3343344433uUUUvV͵tt6ҖLLmmnnnnnmmnmnnnmmnmnnmnMMMLMMnLML֏޲Yəy9xwWWV76řޘҷWV8yWWX77wXwVvvVv5֤U43uը4Ԩ222TԨլԬӬ46Vvwwwږ334433vuuT֕uUs3Ttv޸ޘޘLMMlmmnnmnmnnnnmnmmmnmnmMMMmMMMLLoޱzZҹŹəY8جxxwWW766Wxww9YX78X7Xɶv6Vը֬ըU4tvvդvִr23ԨԬssssUVvږv޶333443333UtږޕڵT͔2StVַޗޘޘ޷ޘLLLMmnmnnmnnmmmmnnnnnmmmMLmMMlMMnڱz:ɹřX99بxxxxxwWW77xޙWWWx8XxwWڗW׬ר֬7U6vu547v֗wVΔӬR2stttssRRSsrsrSRtU֕޵44444444444ޔsړ޴ޓޓ1ɒrVַޘޘޘ,LLLMMmnnnmnnnnnmnnڍmmMMMMMmLLLM֐޲zҹřYYبxXWwww766XژWW777ř8ַŷ9vvvU6vVvV5v8V77W777ִѨ2rӬUutTTsSSRRRRSrRRSRSsԬ4Vu444444444ޒޑޱްޑ1ͲU֗޷ޗxwxwwww,LLLLMmmmnmnnmnmmnnnmmmMLmmMmLLoڲ:yyX88XxwwW676֬8ҙw76vVvwWvvtU565tUVҷޕXx567X4Q1ӬTuŖɖuӰR3RSRS2222R2RSRsr45֔444444444443ޑQ5֗޷ޘޘwwWwWW,L-LMMMMmmnnnnmnnmnmnmmMMmLMmML֐޳:yy898بxxwW6ι7wwŗŷŗv666UU66V5V44tv6җvTyY4Ҕtuŵ7WڴҬӬ3ŕɶvӬR2322222212222RS4Ҕ33444444433TT3qRUw޷ޗޗޘxwWXX7W8,,LLLLMLLMMmMmnMmmMmnڏޯޏގmMmMLNڱޘyښ޺:љyY98بxwxw76vyX֗Vvͷͷɘw65655T4WWuzYSSStӬ55t78SҬ3UuTӨ222222222122RSsu5Ҕ34444434443UUڗޘww8787,+,,MMLLMLMlMMlmmMmڏޯްmmLLڏ޳ޗZZzںޚޚZҚřXYبwxwwV66VXWwX8888җ55vv3St3ԬsssS484rRQqrӬv42212122rR2s5֔4444444443VvwwxW8ҎގMLLMM,MMMMMMLMMLmְޏޯޏޯޯlMMְ޸y:ZZZ:əyY9بwxxxww7767ŗYXYztVVuT654TŖUTΖ޶4SsSsssSs4Ҩ111QrrԬ5Ԭ2211122ssTڴ434444444438Vw6wX7͎nڎL,,LMMMLMMMLLMMڏޯޯޯޯޯޯmLmڰx9Źɺ͹yX9XWWWWW777Vx87֗8yzz:XVT55t4TTɘ԰tTSrStsTuQ01P1QrӬԬӨQR0Ѳ23RsTѕ444445443vwwX75uڵnnڎLL,-L-MLLLMMMML֯ޯޏޯޯޯޯޏޏmLnڑxҙYyźɹ͹Źyy8جبW6666wYvVֵ7yYڷɗWwxUuvs44wږwڕ԰sSSRRRRRR2RssӬu0011RRsӬӨ1012SssԬt5֔4444444444Wvw77vxzzznmL,LL,L-M-MLMLMMگޯޯޯޯޏޯޏڍL֎ޱYy9XYyyřŹŹřřy98جxVz6w8vڗ6ҕyڗ7x8uT͸VִհSsSsSsr2Ss2R5SSs011RRӬ󬱠Q222Rsu4444444548XX޸wW7V7Z9nnL,,-,M-LMMM-MLLL֏ގގޏޏڎޮޏޏmM֏޲xYy999YYyyyxYX8جy8667Vv9y7wڷW7Ҙx6ҷɶŕ7Ҷs3͸wӰԬtsr2RRr2111R22SsӬQ1qӨ4ҨqQ22222RsVڶ4445455444XXxx7޸ޘxXV֗8X9,+L,,,,LL,LLMLMMMMnگގޮޏގگڏLlڏ޳xYyY8899YyzxyyY89Wu67u͸ޙYޗ8X֬֬v6VvŖu34t԰TRS22RR2R1111QrsSr5q0pӰTѨQ123St5Ҷڲ444455455544Xyyޘwژޘޘޘ޸޸ޘޘޘޘWWXyz8XL,,,,,,L,L,LLLMLMLL֏ޯޏڏގڰޏklmڰޘy9řY9Y8YXyYyYX98רجvW6U9U5Tyv9UUհŗ3tuT5tRsrrQQ121Q100qRSrӬ40QrPrQrqӬ4uQ233Sw55455545444T87tu޷xxxwxxxޘxxxޘywXwXzX8޹ޙ޹,,L,-,-,-,,M,,L-MMLLmڎގގތލޯZ9ɺřyY9YYX9Y89بwwV688ޖ޵Y7׬uUWԨyu4ӬT԰v1RQQQR1110QS2rr4tupQ000Q1qҬTq2223233s7ֶ54555UVV5544TvڗޘXwXWXXWxXxXxWWWYyxxڹXy89͙YL,,,,L,L,-M,,MMLM-M-LlڎZɺzy9Y9899ججw7wV78Yޕ:ζ7VuvuvUVW76ְ5ӬvURrQQR1111010RRRTŴ2p01000RT3S3rRssss3sUҗ޷Xy555556VUU6V55vwvV5WwژX7W77877777WWWֶy8XXֹx9ιɹɹyy9L,M,M,,,-,,L,L-LLMLm֏z:͹ɹyYY9998ججبw7WX5u67Xyװut5uVɵ5uwVtstԬӨԬRR11111111111RQRSWШO/PPST2򰲬Ұ3򰒠SSsSs4Wږޗ޷޶555656666555sɶŷUԬ4XWW76Vvڗx8WҘڸιŹxxY8LLL-,,,,LL,LL,-,,MnZɺřyyY88ببפVV8Wvvw֘x֨֨UuUutլ֬uuUըttTTԬԬUrQQQR1110100111QR4r4xVSO0P򬑨qqӰ򬳤332333s6Vwwޗ޶ޖ޶޶56556656555W77ζutX7VږXxW6ҘəřxYXmLML,L,,,,L,,,,MMҏzɺřyyY8ججببw7V89suW޸׬vҶu4uTUs64UT4utt3uŴQR1Q111011010QQQQӬ3sV6֓oPqPq0QrqrӬҬs333T66WVvږޖޖ޷5565655555Wtږޖvv6337ҕWWxW֘ɘyxxX8m,,,,,,,,,L,,M֐:əyxYX9רبW7W98޷57җ68װ׬v7wwլuUլ5SuuլU4uuutӨԬ111111Q00Q0000PQ2SrppQ00000PQqqӬҨ223RU77֖޶ڗ޷555Vޱޒ޲ޓs4ҴuW9W7ҘZ[θřX8ج,,,,,L,,,-Mڰ޹y޺ޚޚZ͹əX8Y888جججר7vV88ڷɖΗ87հW65U44U5t5T32111111101101P5/PQҬtɰP0/000/pP11QҬr3R3RS33RԬUŵŶ6v޶޶ޗޖޗ5ްސްސ1ֲőRxzyWW[zwYxxxY8ج٬M,,,,,,,,,֐޲yzYYZzY9͹x8x78ججרW788v7vɗvxw57֬֬vլ4u5T4uST11111111100QqrӬҬS͔p/PP00P1QqҨsSsrUvUT5uږ޷ޖ޷ޖ޶64T{y888XWX9ҘX8ٰجذmL,,, +,,oޱޘޙY9͘Yججببw7Y7Ҙ5җشw7ŗ֬ԬTtSuu44T44T222r1r10110Р0QQrsrQrq00/0P000PQqҨ43SS3Ԭ55u6֖ޖ޷޷޷3SU{yX88yyޘZZ8ɚw7ذذذٰx,,,, ,,nڑޔޘޘxڸyɸŸŸŸ͹ɘxXذذجج8vWҴ֗7uv6tW֬ըuT3T44t44ըrR2RrUr1RQrqo4oPqQrr1QQqtŔo0/000000QTɴɴɵ͔U55UU֖ޗޗޖޖ޷޶ޕ޶UwYޙYyژxθx89ָ8ذ+,,,, M֏ޒvwxxXژ޹yXXyxŸŸɘxX8׬ذ׬׬׬ج76wֶ9v7Ҹ5t65w֨5լT443U333t3sSr2110otƏ000qQrQqpqqs10///0/0QqҬ3ɴɳŵuԬsTVږޖ޷ޖޖvޖvwޖuޖޕޕ޵ޕ5vwZ޺yX֙ޙXҸyxxιXX9ذذɗm,,+,,,oquWX8Xڙ:ֹy988XyX8׬׬׬װ7͸87ww79޷u6uv5֬Ԩ4443u4tS3svڶrR0ortϜ0010QP0/0QqQpҬSSoO/n/000QrҨ2sSRSŴussvږޗޗvvvvvvVVVuvuޔ޵ޔޔx:޺޺yyڙx9xxX8ذ6,,,,,,Moޓw7XڹYҹy8XX87׬ְw8WwwޗxɸxW779wڵŸŵ4u֬WԨWըUTu2TޕU4ζtTp00OtO00P1P00PPPPPPQ3////Ф/0PҬ2Ѭ24s4җޖޗޖwvWVVVV5665Uuuޕ޴ޕttyY9޺ޚzzڙ޺ޚyxڙX͘xxXذ89xذx5l,-,-,,oޑv7Xڹy9͹y8ذجװw֘889xڷҷW8ZU8ҵt׬6ըX44333Q6Ҷőt3tŔS/0P0Tpn010P//O00/q0pQ//QO/pҬҬtTrԬTvڗޖޗvVV77655utޕޔޕޕޔsy{zZ:޺ޚޚzZZzښYyڙx8͘X88X7ذXVL+,L,,,MpsVwYڹxѹyװجذװX9Zz{zzY9x޷vvW֔u7uvu45ttt33S4sҬӨSœPrO00oP//O0///00PPpqҬ/////0򬑤qpqqqSɶUԨҖޖޖޗvW65Utuޔڔޔtޔ89Z{:[޺zZ;:ZZ:y88ҘŘx88׬W6+K,M,-L,,nڑtXxW8֘޹XїXج׬Xڸ::Zzzz9zyYWW6WV͕լwwW֔vרVVT42tֲ򬒠r2QRRӬUғ2O0O0/0O////0P/000qQPq////ѤS򬑠qpqPqpӰS7V͖ޗޖޗwv665UTtuڔޔޔޔޔttޔ[;ޛ޺ޚ[;9ҙXXҷxxY8٬جججWx7L-L,L,LMM֏ړv7Ҹ8Y8ɘ8׬װ׬׬װx8x:ZZZ9y9֙9xxYZx֘vuVuu65ԠU2u沤221110pѨӬ5p0000//O/O////0/000PQp//0.r2qqpQqҰsvږ޷ޖvVV64UUTTtutTsޔޚZZzںޙzښښ[;ɺź:9yڙXɹɘ88׬ججvLLL,LMMLMpޔV8֘x88͸XذxX֘9X9ə9899YzZwWwѷլ׬xVVvv֤WԠt323SΖ4sQr110P0011q33Q00/P0///////P0//PP00Pp/oQŴ񨐜ppPPOPpPpqtɶv7֗ڗޖޗޗvVV55444UTTTTTڶYY:999ZZz֛[:ŹzYyyy9978جبW67xM,LM-MLMnڑu7X8YYɸɘx787XX8XXY9XX޸89ZY:y7ͷV֬WvuVWUVvw54t4VҐ5Αr11Q000011QQP//PP0O/////N//P0///100qO/O𨓹qpPO//000QpPQqStUV6ҖwvwvvvUU5sStx9yzYZy֚{:źŚY9Y֙ڙyXɘW7X8بWWYxWLMLMLMMMnޒuҸXyyxX7XxxŘŸɸ98XXڸ8֗8ͷլwWUVu454T43Q6ғ򬓤r1QQ00000000q00/P////O/O////00p0pp//S2///////////PPPPpStԨ6vvvvVuuU֔5T͸޺{:řyY8yyyYҘ87x8ww7787LMMLMLmMosVҗ8yYјWWxŸɸ9ҷɹXҸ9ޘذy8yޘwwֵv5ը7V35u4446ҔШ1rqR1P110010p//0////OO//0/P/0p1PQPp//Ф/////0//0/0PPPQQSҵ56UUUuu޴W4ɴҖXָŘz[{:ŚyX8Y88Ҙ͸بwv6ͷMLLMMMMmos6X88͗WWΘŗyXڹXXy9xXxޗw7Ҷv5v֨5Vv54T3QRwRSrӬQQr0q000/0000/0////.OOO/O///P00P0qPoФѨ////0//0//00001QV6͕65Uڕ޵RTɴŴŴUҘ{{:Źy98Ҹ8W8XwwVwvLMMMMmMMpsҷxŸx77ͷŘxW7ҸҸəxxyYجXxxҘw7ɷvVwv5WְT5xvը֤u5TSQѨ԰00P010QosϠ00P//////O/O/O//O0/P0PPqPp2.///0///0/001ҬwVѵUW5uڕޔsTUUUɵɵŴŴ5֗Ҹ[Zzźy99xҸŘ7WxxwW6ŖVMmLmMMLmڏTҗww׬887w͗wwW7yޙXwWޘyxژYYذw7XvڷW6WUְ67Ԭuu45443ůqRQRQQPPP001P0/p0/0p///./.O././/O0POQ0qPPQ2SS2///P////0/0011rt56͖v6wWW5UuuޕޕޕuɴŴwژ޸yyz:źyY99Y͙X7ŗXxx77״x7W6MMMMmMMnpSwwWجװ֬7͗W777WҘxڸ8X9W7xyYx7y8xx޷Vv7w75V67uwuuU5Tt/ϠQ6QQPPP0/P000/ѽO//0PO//O///O////OO0/0PPPP0OѬ2SSSШN/////00000000RT4S66Wxx֗w6WVV֗ޖޗޖUɴ7XXXy9͸::9ŹźřyYYY99جج٬ذXɗw6جwWXwMmMMmMnmpSww7wװ7WŖɷɖvVWWwxޙx8WژY89ذ7v7xX8ҷΗŷ5455WuVv6T31půШTQr11000P0//00Op0/0O/Op//NOOO///O/p/Q/p0/q22N///000010rӬtV6677w7676wڷޖږ5εɴ͹ɘŹYYYY99جج٨بxXXװ7װW7WvMMmMmmNmoSv֨w7w6vŖŗŖwvvWxYڷ8X7vڹ9٬wWɘږŷŗڶUUV744T֬V5Vv55321/Q撽ϤqR101Q10//00//0//P///////O.//../O0p///Ѭ3O///00/010rsV667W767Ww֖WVͷXɹxYŹŹyYY9XببجججXwذ׬׬76VmMmMMmnno3v֨w6W6vuvvvwڸ֗׬ɘ9XҙVζ͵77֬uSuU4211qpQTRœҨ000//0/000////O//./O../N/OPO//NѬqoopѨ32O///0/1Qrrrrrr6W67WWWwWW6wWX8y:9ΙyY989ججWvw֬x7WVMmmmmnmno3ɖV7W6vvŖŖŖw:;x׬{{zޙXWX7ҵX6޷ޖ7հŕ4t44U451ppPqҬpoQsp000/////0//P0/0///0PO/.O//ONN///..O././.ѬoOOppҨS///000/01rRqQRR56ɶ7WxxW7ҷ779ɹXYzzY9ɹY9yYYجxV778V׬WmnmnMnnmoR͖v77רVŖɶɖw::xx{yx7WWy76Xwְvut33U43332rqppQqѤ01100//0/00//O/P/0/////PO///PO/N/OOOO......nϨUNoOOp///0/00/00011qRQRQQQRҵtuW7ɕu77x9͸XYͻ{͙YYYY9ببxXXx7777Wװ׬7nmMmnmnnnQҵv7Vװ7vɶWڸxw׬ذY֙ŘX77WWV6WWuu4Tt43444SqqҬҨѨqpШP1P01Q0P/////0////0//0/p///P.//O.//N.N..O...nnNO.NO/PѨOP//0O/000QqqQqQQR22RT4uɶŕU4UV7ֶ689ҹXx:һyyκyY89بWWw777677wר׬װ׬7nmnnnmnnmpҵ6vvͶ7֗Xxججج8x͵VUv54uְUwtT33333210Ѭ4q1qӰQ1q00///O///O///0////////P///////./N/N/././..oOO.NN.../P/ppѨo/0/qqPqqQqQQ111rt󴳨3ɴŔvv544uW7ַ7֬:ΙYy9z9ҹXřyX9جبX7WWW776V77פx֨׬xnnnmnmnڎmo2v֬77ͶɕŶwڹXwججج77X7UVw6uְvvVvTU4TT433331110Q򰲤ӰPP0P0O0//OO////P///OOOp//0P//../O/O..ON...oOO......O.O/Pqp0//0PQQqQq111tSRrtT44TWҸרYɹXY9͙͘yY9ججWW7WvW776V76v֠נ֨׬ְnmmnnnnnnnQɕvɶŖɕŕї޹wxxޘޙxַw7װYְְ5֬5tU55U4434321qPPQ󴓨q0000P00/00/0///0/0/O//P/O////////.O..NN/.......///..NNOPQPp//////01QqqQ11tr1P884T4T4WxװyXY͸ŘyyxYبW77ww77667V֤֠6nnmnnڎnnnڎoU׬vŶɕŕ7֘޹W778xy8xx77W֬V6ְ6֬֨VըUS4t3433233qqQ1Qr1000P0/00////P//0//OPO/////P//.O........n.///......N-O/00p./0000111Q3TQ11RTŵŖŖv6WX׬׬׬YyWZyYxX9W6Vללv6766666v֨פ6nmnmnnڎڎnnnQu6vɶŖŶ7֙x77YXW׬xW7w6լVt6U4wT45u44t3333RrœŲRrqrQ00/P/0/0O/P/p///OO.O//O/p/OONN.....-.nNNN.NO-..-/.NO/PPp񬰨O//0Rq111P2tŶͶŗu7wҸ׬ذYXY4XxyyY8جV76w֔66666פnڎnnnnnnnnnoUVuɵ7Wx8ѶW78wxxw7X77w7Vuְְ6UT4tTT3S3333а5T3qQPpQr0000/P00///0/O//0/p/OO/O////O.O./.......OoONNO.NN.-....OOPO0񰰬ѬѬo/010Q111RsӬUuvv56ָ8Ҙ788Yx6YyŘXxy8جببV66W6666667Uפw5nnnڎnnڎڎnڎڎnp͕ɕ7і7Ww8ѷxWWWXW6լ7uԨ33TUTT4St3322Ҵɰ3TS4r3PQqQPQOq/0O///OO///O//////O/P.O...OoN.. .NnNnnONM.N........OOO0pѬѬѬo/000000Qqq112qӬԬu6zZxɘxX88X8y8XxX8جب٨V76666666666666656հVnnnnnڎnڎnڎoގn1͵7ɸɶw787רwWWW7W7667ְtU33tTT3433331Rζ3QQ0Qq00P0q/p00//0//0/////PO/Oq//O... MРnN..-аpNO.NNNNN..N.oOPO00ѬѬѬѬ񬱨p0p񬑤010QҰҬ11RհԬu7w:ŹY8Y88xX9بxלw766V6V5V5U656mnڎގnnnnڎoڎnڎpіŖxw68WwW7776W׬x76vtִTwլT2st233433322ѨUsųɲ4rP0000PQ0P0/PP/0/OO//P/P0/O/OOOO-. РM.NϬϨoON.M-N-...-NNrO//OP񬐨opѬѬ򬐤OŵɐPqҬQ112RԬԬTXxWWWW7789ɹX88׬8X88بww66VVVVV56VV6666tWֶɎnnڎڎڎގnڏގoڏޏp3ɗwY֙WvY7֖֗vw7WwvW76մST4tT233Sլ333t32QѤqTQ1p1Q0///0O0/Q0//OPPO///P///pONNN... -rmNNnoo/.-NN-NnoNNNNo/P/0poOoШҰsSqPҬҬҬP2222RWw79xX͸ɗŸŘ7Y8׬׬׬جרxw766VVU5VUVU5666665xڵnڎnnnڎnڎnڏޏoڎp4ɖuəx66WvwҸVWWv66լv6ְSS333SSS322qШҬ11R1qP0/OP0//P00P0/O/////O/O//OO/-..-.- -  -Q...OON..-....-.N../P/o񰯨OOOOopoOҰѬoP/ҰҬҬҰ򰱤r112R77ҖwŗxwXWwwXXX׬׬جwWw66666V5UUU65556VҎnڎڎڎڎnڎގڏnڏޏq5ѵɖvwVvXҙ8ҷ6wWɸWvw7wWԬհttUtts33333S3330S1rΒp0qQ/p/////////O/PO0PO/Np/P/....-. .. -/.N......-NN...O/.PPNOnoOoNpOppP00032ѬѬ23STS3󰳬ӬT͗WVWVwWWW7֬x8ج׬װ8XŸŘجww7777677675565UU5V555Uunގnގoގގڏޏڏޏޏޏr͕UU5VxژΗwɗWWִ667WVլհլְ333333333S22Ѥ3r0q10P0/P////P////OO///p//O..M.o.... -.--- lN.NN..--.-M.N-.O.p/񬯨onnOO/pppPqPO/P2S񬱨Ѩ2SStut3TUvUVv78ɸɘX7׬׬887w8xwwږѸ776555U65656uvҵnnڎގڎڎގڏޏޏޏޏޏSֶU5xYw6ŷw׬w7WְVttTtT333333332321qѨpQPPP0p//////////O/N/O./...-. ...-.-.OM-.  oΤ......NN......OP//ЬϬooN.//NOpPppO/pPqҬҬ33T3UɵuW8ҹy8֬׬װ{:TTvx׬w76667666655U555555ړڎnڎnڎގڎڏޏގڏޏސSѕU58xvŷWvwW6UլWWutt4T33SS3333S222R00/qQ0PO////OOOO/////.//....--../-.-NN-.MRMN...M-N...N/NN/././/OOpqppѬpO/P0PQpѬ3T8ɖ7͘Y87X8׬֬99u3S8ŷxר766פXv5555555445հSnڎގގގnގޏޏޏޏޏڰSu5555VɷvլvvV6vUTըuWԬtְSS33333332oѬOҬOҬpq/P/0P/OPONO../../... -N..--Nn--.Nn-...- ..oo.-...NonN/N...N/O/OOPpqѨO//00PpppqqɶSz66ͷŗ7X88֘T֕Y{WY5776՜65555545462oގގڎޏގޏޏޯޏޏޯޑ4U5U655wŷVV6U66հtTvޖ޶ɵ6St333s33SS333S2R񬯠pOpoOPp/p//OO////O./O/./. -.MN-n-.-N-N.. nm ..-.- -.-.../QϤOnnO./...NNO//OP//0//OPpŕ64VҗvwvvW7W8ֶv6wwx֤876655455555ҎڎnގޏޏޏގޯޯޯޏޱTڴ4VVV6ըvv665U5uuޔլUtSTT333343SSR220nS//NNp/P/OpOoO/O/OO///. .--MmM-.-.nN.N.....,n,M0-  ../.nNNNNN..N.NOO/O/0PPO00/00PpRvuҬuvWVW68֘WWɚZڗW͘wXxɘ5U555554544tusڏގޏޏޏޮޏޯޏگޯްް4ڴ4ԬVV6V6u5us6֬լլTU3T3SSS332s20qopO./p/P/pOpP/0NPo./O./MMNomMNN........- MϤΠl  ...OΤONNnnN..N.NMpO/O/0PO/0/OOֲ22t԰Uu5ӬҬ6V66V66WW67ֹxwXxW455555455T5ڕ޵ִޯޏޏޯޏޏޏޯްްޱ4ڴ4Ԭհ5V65utuU555Ŵųvޔ԰s2TtS3ըSS3333R21/02pp/O/0///P////////.//.﬎-N.--.--.....N- n1M.. ...n﨎.NNnN...NNNNOOOPPPpPPOpPQuհUѵ5756VWVwլ68xڙ޸޷WW8җX5554454v5tޏޮޯޯޯޯޯޯޏޯްޱTڳԬU6VըըtuuuuU6Uuɓ޵5ִuRS2ԬԨTTtt3sSR3232Rq00oѨOOO/pOp//000///O./// nN.MΤ.-.-.M...-N.-.  mѽOΨN- ..nNN.MNN..NNNNN./OOPpPppϬЬааЬЬ1ɑrųV޶uڵ56V6w67wx8x7W{75545444vɖTŔޏޯޏޏޯޯޯްްSڴԬU5uvըլuTUuu65ŕ3sStҵwTԬSSR3s֨tTssR32qpOOOPN..OO///0////////./..0m.n. .....--MN-..-  .m-pmN-.- ..nNNMNN.....N../.N/OШpͱЬQаpqq6wZ޵5԰56V76VwV6W78X77wҘ7W443Ŵ43ޯޯޯޯްޯް1ҳTŔԤttttT44ԨsѬѬ2qœVsRR111112ԨRsR12110pq/ϤnШ.2n..-.N..P...o...-..- lN.L,.- ,-,,-L-- -- - -- MmmmmLL-----N------.M..-N...NoЬo/ɐOő.55Vִ34TuɕU54Uvw6հ7w7֗U6VɶͷԨ3VvœWޯޯްޯް7~~}]34tŵVwްްޏ7|<]\<\޻޻޺޺޺:޺[;[[;:|<<\|\|==<}]]\|]]===]]==}}޼=VѴUUڼ{<<\]<޼<<޻޻޻޻\;޹;:[;:z|}<\}}=<\]<]<===}]<]=\]\}޼]3567V5ސM{;\\\<<;޻;:޺;;|\}<<\}}<<<<=\<]=\}}==<=<]]]}|=ޞqtŶV65N{\<\]<<<޺<[;:::[\\<<\]\<<<<\<]=<<]]=\<]]\==\<}]]<\޼޼޾VvVڰN[;\|]<<;;;[;[޺:[{;;\|}\<\<<\||}<\]<\==<}\<]<<=\]]}==]=}=Δ85vַ5M{;<]\<<<޻[;|\|;|޺;|[Z{;<\];<|||Z=\|<==]}\\]}<<]]<=]<}<\<|\2ΕV6vڗ5wN{[\\\<<޼<<[{{޺[[|[;[||<\||||}\|\<<<\}|<|\tuUU֗vuָVn{{;<;<<<<޻|[;޹{{};;||\\<<|}|}<<<<==};\\LoadResources(*_theme, _subVramContext); _bottomBackground = _theme->CreateRomBrowserBottomBackground(); _bottomBackground->LoadResources(*_theme, _mainVramContext); - - _materialThemeFileIconFactory = std::make_unique( - &_theme->GetMaterialColorScheme(), _theme->GetFontRepository()); } void App::VCountIrq() @@ -138,7 +135,7 @@ void App::Run() &_romBrowserBottomScreenViewModel, RomBrowserDisplayModeFactory().GetRomBrowserDisplayMode( _romBrowserController.GetRomBrowserDisplaySettings().layout), - _materialThemeFileIconFactory.get(), + _theme->GetThemeFileIconFactory(), _theme->GetRomBrowserViewFactory(), &_vblankTextureLoader); _romBrowserBottomScreenView->InitVram(_mainVramContext); @@ -253,6 +250,7 @@ void App::HandleTrigger(RomBrowserStateTrigger trigger, RomBrowserState newState { case RomBrowserStateTrigger::None: case RomBrowserStateTrigger::Launch: + case RomBrowserStateTrigger::GotoSettingsScreen: { break; } @@ -344,7 +342,7 @@ void App::HandleFolderLoadDoneTrigger() _romBrowserTopScreenView = RomBrowserTopScreenView::CreateShared( _romBrowserController.GetRomBrowserViewModel(), displayMode, - _materialThemeFileIconFactory.get(), + _theme->GetThemeFileIconFactory(), _theme->GetRomBrowserViewFactory()); _romBrowserTopScreenView->InitVram(_subVramContext); _romBrowserBottomScreenView->RomBrowserViewModelInvalidated(_mainVramContext); @@ -361,7 +359,7 @@ void App::HandleChangeDisplayModeTrigger(RomBrowserState newState) _romBrowserBottomScreenView = RomBrowserBottomScreenView::CreateShared( &_romBrowserBottomScreenViewModel, displayMode, - _materialThemeFileIconFactory.get(), + _theme->GetThemeFileIconFactory(), _theme->GetRomBrowserViewFactory(), &_vblankTextureLoader); _romBrowserBottomScreenView->InitVram(_mainVramContext); @@ -369,7 +367,7 @@ void App::HandleChangeDisplayModeTrigger(RomBrowserState newState) _romBrowserTopScreenView = RomBrowserTopScreenView::CreateShared( _romBrowserController.GetRomBrowserViewModel(), displayMode, - _materialThemeFileIconFactory.get(), + _theme->GetThemeFileIconFactory(), _theme->GetRomBrowserViewFactory()); _romBrowserTopScreenView->InitVram(_subVramContext); _romBrowserBottomScreenView->RomBrowserViewModelInvalidated(_mainVramContext); @@ -377,16 +375,6 @@ void App::HandleChangeDisplayModeTrigger(RomBrowserState newState) _romBrowserBottomScreenView->Focus(_focusManager); } -bool App::IsRomBrowserVisible() const -{ - const auto& stateMachine = _romBrowserController.GetStateMachine(); - auto curState = stateMachine.GetCurrentState(); - return curState == RomBrowserState::Browser - || curState == RomBrowserState::GameInfo - || curState == RomBrowserState::DisplaySettings - || curState == RomBrowserState::Launching; -} - void App::Update() { const auto& stateMachine = _romBrowserController.GetStateMachine(); @@ -402,8 +390,10 @@ void App::Update() HandleTrigger(stateMachine.GetLastTrigger(), curState); } - bool isRomBrowserVisible = IsRomBrowserVisible(); - if (isRomBrowserVisible && !_exit && curState != RomBrowserState::Launching) + bool isRomBrowserVisible = _romBrowserBottomScreenViewModel.IsRomBrowserVisible(); + if (isRomBrowserVisible && !_exit && + curState != RomBrowserState::Launching && + curState != RomBrowserState::GoingToSettingsScreen) { HandleInput(); } @@ -456,7 +446,7 @@ void App::Draw() if (_bottomBackground) _bottomBackground->Draw(mainGraphicsContext); - if (!_changeDisplayMode && IsRomBrowserVisible()) + if (!_changeDisplayMode && _romBrowserBottomScreenViewModel.IsRomBrowserVisible()) { _romBrowserTopScreenView->Draw(subGraphicsContext); } @@ -499,7 +489,7 @@ void App::VBlank() _dialogPresenter.VBlank(); - if (IsRomBrowserVisible()) + if (_romBrowserBottomScreenViewModel.IsRomBrowserVisible()) { _romBrowserTopScreenView->VBlank(); } diff --git a/arm9/source/App.h b/arm9/source/App.h index f424e6c..fb74551 100644 --- a/arm9/source/App.h +++ b/arm9/source/App.h @@ -25,7 +25,6 @@ #include "romBrowser/views/RomBrowserTopScreenView.h" #include "romBrowser/views/IconButton2DView.h" #include "romBrowser/views/ChipView.h" -#include "romBrowser/Theme/Material/MaterialThemeFileIconFactory.h" #include "romBrowser/RomBrowserController.h" #include "DialogPresenter.h" #include "themes/ITheme.h" @@ -90,8 +89,6 @@ private: FocusManager _focusManager; - std::unique_ptr _materialThemeFileIconFactory; - RomBrowserBottomScreenViewModel _romBrowserBottomScreenViewModel; DialogPresenter _dialogPresenter; @@ -121,8 +118,6 @@ private: void HandleFolderLoadDoneTrigger(); void HandleChangeDisplayModeTrigger(RomBrowserState newState); - bool IsRomBrowserVisible() const; - void MainLoop(); void Update(); void Draw(); diff --git a/arm9/source/bgm/AudioStreamPlayer.cpp b/arm9/source/bgm/AudioStreamPlayer.cpp index fa8c241..572b040 100644 --- a/arm9/source/bgm/AudioStreamPlayer.cpp +++ b/arm9/source/bgm/AudioStreamPlayer.cpp @@ -32,7 +32,7 @@ bool AudioStreamPlayer::StartPlaybackIntern(std::unique_ptr audioS StopPlaybackIntern(); _audioStream = std::move(audioStream); - + // fill buffer _readBlock = 0; _writeBlock = 0; @@ -83,10 +83,10 @@ void AudioStreamPlayer::StopPlaybackIntern() return; _isPlaying = false; - rtos_wakeupThread(&_thread); ipc_sendFifoMessage(IPC_CHANNEL_SOUND, (u32)&_soundStopCmdList); tmr_stop(AUDIO_STREAM_PLAYER_TIMER); rtos_disableIrqMask(RTOS_IRQ_TIMER(AUDIO_STREAM_PLAYER_TIMER)); + rtos_signalEvent(&_event); rtos_joinThread(&_thread); sCurrentPlayer = nullptr; _audioStream.reset(); @@ -97,7 +97,7 @@ void AudioStreamPlayer::ThreadMain() do { bool doUpdate = true; - while(_isPlaying && doUpdate) + while (_isPlaying && doUpdate) { rtos_lockMutex(&_mutex); { diff --git a/arm9/source/bgm/AudioStreamPlayer.h b/arm9/source/bgm/AudioStreamPlayer.h index 7e9bb93..930254d 100644 --- a/arm9/source/bgm/AudioStreamPlayer.h +++ b/arm9/source/bgm/AudioStreamPlayer.h @@ -93,8 +93,8 @@ private: rtos_thread_t _thread; rtos_event_t _event; volatile bool _isPlaying = false; - volatile u8 _readBlock; - volatile u8 _writeBlock; + volatile u8 _readBlock = 0; + volatile u8 _writeBlock = 0; std::unique_ptr _audioStream; static AudioStreamPlayer* sCurrentPlayer; diff --git a/arm9/source/bgm/BgmService.cpp b/arm9/source/bgm/BgmService.cpp index 54e86af..b79bfef 100644 --- a/arm9/source/bgm/BgmService.cpp +++ b/arm9/source/bgm/BgmService.cpp @@ -12,7 +12,7 @@ bool BgmService::StartBgm(const TCHAR* filePath) auto stream = std::make_unique(); if (!stream->Open(filePath)) return false; - + return _audioStreamPlayer->StartPlayback(std::move(stream)); } diff --git a/arm9/source/gui/views/Label2DView.cpp b/arm9/source/gui/views/Label2DView.cpp index 5b286b0..d147ae8 100644 --- a/arm9/source/gui/views/Label2DView.cpp +++ b/arm9/source/gui/views/Label2DView.cpp @@ -59,7 +59,7 @@ void Label2DView::Draw(GraphicsContext& graphicsContext) void Label2DView::VBlank() { - if (_tileBufferUpdated) + if (_tileBufferUpdated && _vramAddress) { memcpy((void*)_vramAddress, _tileBuffer.get(), _tileBufferSize); _tileBufferUpdated = false; diff --git a/arm9/source/gui/views/RecyclerAdapter.h b/arm9/source/gui/views/RecyclerAdapter.h index fb77b9f..58cfcbc 100644 --- a/arm9/source/gui/views/RecyclerAdapter.h +++ b/arm9/source/gui/views/RecyclerAdapter.h @@ -1,4 +1,6 @@ #pragma once +#include "core/SharedPtr.h" + class View; /// @brief Adapter class providing the content to show in a \see RecyclerView. diff --git a/arm9/source/romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.cpp b/arm9/source/romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.cpp index 11ff06d..8805e45 100644 --- a/arm9/source/romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.cpp +++ b/arm9/source/romBrowser/DisplayMode/CoverFlowFileRecyclerAdapter.cpp @@ -5,6 +5,7 @@ #include "../Theme/IRomBrowserViewFactory.h" #include "../FileType/UnknownFileCover.h" #include "romBrowser/ICoverRepository.h" +#include "romBrowser/viewModels/RomBrowserItemViewModel.h" #include "CoverFlowFileRecyclerAdapter.h" void CoverFlowFileRecyclerAdapter::GetViewSize(int& width, int& height) const diff --git a/arm9/source/romBrowser/IRomBrowserController.h b/arm9/source/romBrowser/IRomBrowserController.h index 343d75a..d88a232 100644 --- a/arm9/source/romBrowser/IRomBrowserController.h +++ b/arm9/source/romBrowser/IRomBrowserController.h @@ -24,6 +24,7 @@ public: virtual void HideGameInfo() = 0; virtual void ShowDisplaySettings() = 0; virtual void HideDisplaySettings() = 0; + virtual void GotoSettingsScreen() = 0; virtual void Update() = 0; diff --git a/arm9/source/romBrowser/RomBrowserController.cpp b/arm9/source/romBrowser/RomBrowserController.cpp index 1a4eabc..e530f87 100644 --- a/arm9/source/romBrowser/RomBrowserController.cpp +++ b/arm9/source/romBrowser/RomBrowserController.cpp @@ -2,6 +2,7 @@ #include #include "picoLoaderBootstrap.h" #include "PicoLoaderProcess.h" +#include "settings/SettingsProcess.h" #include "FileType/ExtensionFileTypeProvider.h" #include "FileType/FileType.h" #include "SdFolderFactory.h" @@ -60,6 +61,11 @@ void RomBrowserController::HideDisplaySettings() _stateMachine.Fire(RomBrowserStateTrigger::HideDisplaySettings); } +void RomBrowserController::GotoSettingsScreen() +{ + _stateMachine.Fire(RomBrowserStateTrigger::GotoSettingsScreen); +} + void RomBrowserController::SetRomBrowserDisplaySettings( const RomBrowserDisplaySettings& romBrowserDisplaySettings) { @@ -128,6 +134,10 @@ void RomBrowserController::HandleTrigger() HandleChangeDisplayModeTrigger(); break; + case RomBrowserStateTrigger::GotoSettingsScreen: + HandleGotoSettingsScreenTrigger(); + break; + default: break; } @@ -213,6 +223,11 @@ void RomBrowserController::HandleChangeDisplayModeTrigger() _romBrowserViewModel = SharedPtr::MakeShared(this); } +void RomBrowserController::HandleGotoSettingsScreenTrigger() +{ + gProcessManager.Goto(); +} + void RomBrowserController::UpdateLastUsedFilepath() { f_getcwd(_navigatePath, sizeof(_navigatePath) / sizeof(_navigatePath[0])); diff --git a/arm9/source/romBrowser/RomBrowserController.h b/arm9/source/romBrowser/RomBrowserController.h index f8ddc7b..7dc3623 100644 --- a/arm9/source/romBrowser/RomBrowserController.h +++ b/arm9/source/romBrowser/RomBrowserController.h @@ -30,6 +30,7 @@ public: void HideGameInfo() override; void ShowDisplaySettings() override; void HideDisplaySettings() override; + void GotoSettingsScreen() override; void Update() override; @@ -80,6 +81,7 @@ private: void HandleFolderLoadDoneTrigger(); void HandleLaunchTrigger(); void HandleChangeDisplayModeTrigger(); + void HandleGotoSettingsScreenTrigger(); void UpdateLastUsedFilepath(); void SetPicoLoaderParams() const; void LoadCheats() const; diff --git a/arm9/source/romBrowser/RomBrowserState.h b/arm9/source/romBrowser/RomBrowserState.h index 9099b03..6c2972a 100644 --- a/arm9/source/romBrowser/RomBrowserState.h +++ b/arm9/source/romBrowser/RomBrowserState.h @@ -7,5 +7,6 @@ enum class RomBrowserState GameInfo, LoadingFolder, Launching, - DisplaySettings + DisplaySettings, + GoingToSettingsScreen }; diff --git a/arm9/source/romBrowser/RomBrowserStateMachine.cpp b/arm9/source/romBrowser/RomBrowserStateMachine.cpp index 11796c4..98b5cdf 100644 --- a/arm9/source/romBrowser/RomBrowserStateMachine.cpp +++ b/arm9/source/romBrowser/RomBrowserStateMachine.cpp @@ -28,6 +28,7 @@ bool RomBrowserStateMachine::FireDirect(RomBrowserStateTrigger trigger) .In(RomBrowserState::DisplaySettings) .Trigger(RomBrowserStateTrigger::ChangeDisplayMode).GoesTo(RomBrowserState::DisplaySettings) .Trigger(RomBrowserStateTrigger::HideDisplaySettings).GoesTo(RomBrowserState::Browser) + .Trigger(RomBrowserStateTrigger::GotoSettingsScreen).GoesTo(RomBrowserState::GoingToSettingsScreen) .Check(newState)) { _prevState = _curState; diff --git a/arm9/source/romBrowser/RomBrowserStateTrigger.h b/arm9/source/romBrowser/RomBrowserStateTrigger.h index 58473d5..cd9be6b 100644 --- a/arm9/source/romBrowser/RomBrowserStateTrigger.h +++ b/arm9/source/romBrowser/RomBrowserStateTrigger.h @@ -10,5 +10,6 @@ enum class RomBrowserStateTrigger FolderLoadDone, Launch, ShowDisplaySettings, - HideDisplaySettings + HideDisplaySettings, + GotoSettingsScreen }; diff --git a/arm9/source/romBrowser/SdFolder.cpp b/arm9/source/romBrowser/SdFolder.cpp index a52dca1..0392593 100644 --- a/arm9/source/romBrowser/SdFolder.cpp +++ b/arm9/source/romBrowser/SdFolder.cpp @@ -14,10 +14,10 @@ SdFolder::~SdFolder() } std::unique_ptr SdFolder::FilterAndSort( - const SdFolderFilterSortParams& filterSortParams, int& resultCount) const + const SdFolderFilterSortParams& filterSortParams, u32& resultCount) const { auto sortedFilteredFiles = std::make_unique(_fileCount); - int filteredCount = 0; + u32 filteredCount = 0; for (int i = 0; i < _fileCount; i++) { const FileInfo* file = _files[i]; diff --git a/arm9/source/romBrowser/SdFolder.h b/arm9/source/romBrowser/SdFolder.h index 49806b7..db2b1e7 100644 --- a/arm9/source/romBrowser/SdFolder.h +++ b/arm9/source/romBrowser/SdFolder.h @@ -26,7 +26,7 @@ public: /// @param resultCount Will contain the number of results. /// @return A unique pointer to an array of FileInfo pointers containing the results. std::unique_ptr FilterAndSort( - const SdFolderFilterSortParams& filterSortParams, int& resultCount) const; + const SdFolderFilterSortParams& filterSortParams, u32& resultCount) const; void SortByNameInPlace(); const FileInfo* BinarySearch(const char* fileName) const; diff --git a/arm9/source/romBrowser/Theme/IRomBrowserViewFactory.h b/arm9/source/romBrowser/Theme/IRomBrowserViewFactory.h index 93a63ea..6658527 100644 --- a/arm9/source/romBrowser/Theme/IRomBrowserViewFactory.h +++ b/arm9/source/romBrowser/Theme/IRomBrowserViewFactory.h @@ -12,18 +12,18 @@ class VBlankTextureLoader; class RomBrowserViewModel; class IThemeFileIconFactory; class FileRecyclerAdapter; -class RomBrowserItemViewModel; +class IRomBrowserItemViewModel; class IRomBrowserViewFactory { public: virtual ~IRomBrowserViewFactory() = 0; - virtual SharedPtr CreateIconGridItemView(std::unique_ptr viewModel) const = 0; + virtual SharedPtr CreateIconGridItemView(std::unique_ptr viewModel) const = 0; virtual IconGridItemView::VramToken UploadIconGridItemViewGraphics( const VramContext& vramContext) const { return IconGridItemView::VramToken(0); } - virtual SharedPtr CreateBannerListItemView(std::unique_ptr viewModel, + virtual SharedPtr CreateBannerListItemView(std::unique_ptr viewModel, VBlankTextureLoader* vblankTextureLoader) const = 0; virtual BannerListItemView::VramToken UploadBannerListItemViewGraphics( const VramContext& vramContext) const { return BannerListItemView::VramToken(0); } diff --git a/arm9/source/romBrowser/Theme/IThemeFileIconFactory.h b/arm9/source/romBrowser/Theme/IThemeFileIconFactory.h index 96158f0..9431f1c 100644 --- a/arm9/source/romBrowser/Theme/IThemeFileIconFactory.h +++ b/arm9/source/romBrowser/Theme/IThemeFileIconFactory.h @@ -9,6 +9,7 @@ public: virtual std::unique_ptr CreateFolderIcon(const TCHAR* name) const = 0; virtual std::unique_ptr CreateGenericFileIcon(const TCHAR* name) const = 0; virtual std::unique_ptr CreateNdsFileIcon(const TCHAR* name) const = 0; + virtual std::unique_ptr CreateThemeFileIcon() const = 0; }; inline IThemeFileIconFactory::~IThemeFileIconFactory() { } diff --git a/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.cpp b/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.cpp index ac0dd43..c4f1078 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.cpp +++ b/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.cpp @@ -18,12 +18,12 @@ #include "gui/views/Label2DView.h" #include "MaterialBannerListItemView.h" -MaterialBannerListItemView::MaterialBannerListItemView(std::unique_ptr viewModel, +MaterialBannerListItemView::MaterialBannerListItemView(std::unique_ptr viewModel, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository) : BannerListItemView(std::move(viewModel), - Label2DView::CreateShared(160, 16, 50, fontRepository->GetFont(FontType::Medium10)), - Label2DView::CreateShared(160, 16, 50, fontRepository->GetFont(FontType::Regular10)), - Label2DView::CreateShared(160, 16, 50, fontRepository->GetFont(FontType::Regular10))) + Label2DView::CreateShared(152, 16, 128, fontRepository->GetFont(FontType::Medium10)), + Label2DView::CreateShared(152, 16, 128, fontRepository->GetFont(FontType::Regular10)), + Label2DView::CreateShared(152, 16, 128, fontRepository->GetFont(FontType::Regular10))) , _materialColorScheme(materialColorScheme) { } void MaterialBannerListItemView::Draw(GraphicsContext& graphicsContext) diff --git a/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.h b/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.h index bba63bd..16d9344 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.h +++ b/arm9/source/romBrowser/Theme/Material/MaterialBannerListItemView.h @@ -28,6 +28,6 @@ private: const MaterialColorScheme* _materialColorScheme; u32 _bgVramOffset; - MaterialBannerListItemView(std::unique_ptr viewModel, + MaterialBannerListItemView(std::unique_ptr viewModel, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository); }; diff --git a/arm9/source/romBrowser/Theme/Material/MaterialCoverFlowFileRecyclerAdapter.cpp b/arm9/source/romBrowser/Theme/Material/MaterialCoverFlowFileRecyclerAdapter.cpp index e6e41a8..2b67fb0 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialCoverFlowFileRecyclerAdapter.cpp +++ b/arm9/source/romBrowser/Theme/Material/MaterialCoverFlowFileRecyclerAdapter.cpp @@ -5,6 +5,7 @@ #include "romBrowser/Theme/IRomBrowserViewFactory.h" #include "romBrowser/FileType/UnknownFileCover.h" #include "romBrowser/ICoverRepository.h" +#include "romBrowser/viewModels/RomBrowserItemViewModel.h" #include "MaterialCoverFlowFileRecyclerAdapter.h" void MaterialCoverFlowFileRecyclerAdapter::GetViewSize(int& width, int& height) const diff --git a/arm9/source/romBrowser/Theme/Material/MaterialCoverView.h b/arm9/source/romBrowser/Theme/Material/MaterialCoverView.h index 82cf65d..ab32ced 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialCoverView.h +++ b/arm9/source/romBrowser/Theme/Material/MaterialCoverView.h @@ -3,7 +3,7 @@ #include "gui/views/View.h" #include "romBrowser/FileType/FileCover.h" #include "gui/VBlankTextureLoader.h" -#include "romBrowser/viewModels/RomBrowserItemViewModel.h" +#include "romBrowser/viewModels/IRomBrowserItemViewModel.h" #include "romBrowser/views/RomBrowserItemInputHandler.h" class MaterialCoverView : public View @@ -45,13 +45,13 @@ public: void UploadCoverGraphics(); - RomBrowserItemViewModel& GetViewModel() const + IRomBrowserItemViewModel& GetViewModel() const { return *_viewModel; } private: - std::unique_ptr _viewModel; + std::unique_ptr _viewModel; VBlankTextureLoader* _vblankTextureLoader; AtomicSharedPtr _cover; VBlankTextureLoadRequest _textureLoadRequest; @@ -59,7 +59,7 @@ private: u32 _plttVramOffset = 0; RomBrowserItemInputHandler _inputHandler; - MaterialCoverView(std::unique_ptr viewModel, VBlankTextureLoader* vblankTextureLoader) + MaterialCoverView(std::unique_ptr viewModel, VBlankTextureLoader* vblankTextureLoader) : _viewModel(std::move(viewModel)), _vblankTextureLoader(vblankTextureLoader) , _inputHandler(this, _viewModel.get()) { } }; diff --git a/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.cpp b/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.cpp index 4cfcd29..153cbcd 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.cpp +++ b/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.cpp @@ -13,10 +13,10 @@ MaterialFileInfoCardView::MaterialFileInfoCardView(const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository) - : _firstLine(Label2DView::CreateShared(176, 16, 50, fontRepository->GetFont(FontType::Medium11))) - , _secondLine(Label2DView::CreateShared(176, 16, 50, fontRepository->GetFont(FontType::Regular10))) - , _thirdLine(Label2DView::CreateShared(176, 16, 50, fontRepository->GetFont(FontType::Regular10))) - , _filenameLabelView(Label2DView::CreateShared(220, 16, 200, fontRepository->GetFont(FontType::Medium7_5))) + : _firstLine(Label2DView::CreateShared(168, 16, 128, fontRepository->GetFont(FontType::Medium11))) + , _secondLine(Label2DView::CreateShared(168, 16, 128, fontRepository->GetFont(FontType::Regular10))) + , _thirdLine(Label2DView::CreateShared(168, 16, 128, fontRepository->GetFont(FontType::Regular10))) + , _filenameLabelView(Label2DView::CreateShared(220, 16, 256, fontRepository->GetFont(FontType::Medium7_5))) , _materialColorScheme(materialColorScheme) { AddChildTail(_firstLine.GetPointer()); diff --git a/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.h b/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.h index 69e9f38..bba692c 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.h +++ b/arm9/source/romBrowser/Theme/Material/MaterialFileInfoCardView.h @@ -25,6 +25,15 @@ public: _firstLine->SetText(firstLine); } + void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, bool ellipsis) override + { + _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); + if (taskQueue) + _firstLine->SetTextAsync(taskQueue, firstLine); + else + _firstLine->SetText(firstLine); + } + void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override { _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); @@ -34,6 +43,14 @@ public: _firstLine->SetText(firstLine, length); } + void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine) override + { + if (taskQueue) + _secondLine->SetTextAsync(taskQueue, secondLine); + else + _secondLine->SetText(secondLine); + } + void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override { if (taskQueue) @@ -42,6 +59,14 @@ public: _secondLine->SetText(secondLine, length); } + void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine) override + { + if (taskQueue) + _thirdLine->SetTextAsync(taskQueue, thirdLine); + else + _thirdLine->SetText(thirdLine); + } + void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override { if (taskQueue) diff --git a/arm9/source/romBrowser/Theme/Material/MaterialIconGridItemView.h b/arm9/source/romBrowser/Theme/Material/MaterialIconGridItemView.h index 6f3048e..db0ce87 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialIconGridItemView.h +++ b/arm9/source/romBrowser/Theme/Material/MaterialIconGridItemView.h @@ -26,6 +26,6 @@ private: const MaterialColorScheme* _materialColorScheme; u32 _bgVramOffset; - MaterialIconGridItemView(std::unique_ptr viewModel, const MaterialColorScheme* materialColorScheme) + MaterialIconGridItemView(std::unique_ptr viewModel, const MaterialColorScheme* materialColorScheme) : IconGridItemView(std::move(viewModel)), _materialColorScheme(materialColorScheme) { } }; diff --git a/arm9/source/romBrowser/Theme/Material/MaterialRomBrowserViewFactory.h b/arm9/source/romBrowser/Theme/Material/MaterialRomBrowserViewFactory.h index 74b0f3e..f7e31c1 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialRomBrowserViewFactory.h +++ b/arm9/source/romBrowser/Theme/Material/MaterialRomBrowserViewFactory.h @@ -18,7 +18,7 @@ public: const IFontRepository* fontRepository) : _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { } - SharedPtr CreateIconGridItemView(std::unique_ptr viewModel) const override + SharedPtr CreateIconGridItemView(std::unique_ptr viewModel) const override { return MaterialIconGridItemView::CreateShared(std::move(viewModel), _materialColorScheme); } @@ -29,7 +29,7 @@ public: return MaterialIconGridItemView::UploadGraphics(vramContext); } - SharedPtr CreateBannerListItemView(std::unique_ptr viewModel, + SharedPtr CreateBannerListItemView(std::unique_ptr viewModel, VBlankTextureLoader* vblankTextureLoader) const override { return MaterialBannerListItemView::CreateShared(std::move(viewModel), _materialColorScheme, _fontRepository); diff --git a/arm9/source/romBrowser/Theme/Material/MaterialThemeFileIcon.h b/arm9/source/romBrowser/Theme/Material/MaterialThemeFileIcon.h new file mode 100644 index 0000000..ea8a8aa --- /dev/null +++ b/arm9/source/romBrowser/Theme/Material/MaterialThemeFileIcon.h @@ -0,0 +1,29 @@ +#pragma once +#include "MaterialFileIcon.h" +#include "themeIconLarge.h" +#include "themes/material/MaterialColorScheme.h" + +class MaterialThemeFileIcon : public MaterialFileIcon +{ +public: + MaterialThemeFileIcon(const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository) + : MaterialFileIcon("", materialColorScheme, fontRepository) { } + +protected: + const void* GetIconTiles() const override + { + return themeIconLargeTiles; + } + + Rgb<8, 8, 8> GetIconColor() const override + { + return _materialColorScheme->tertiary; + } + + Rgb<8, 8, 8> GetTextColor() const override + { + return _materialColorScheme->onTertiary; + } + + int GetTextYOffset() const override { return 0; } +}; diff --git a/arm9/source/romBrowser/Theme/Material/MaterialThemeFileIconFactory.h b/arm9/source/romBrowser/Theme/Material/MaterialThemeFileIconFactory.h index 01ebf3a..b74fa11 100644 --- a/arm9/source/romBrowser/Theme/Material/MaterialThemeFileIconFactory.h +++ b/arm9/source/romBrowser/Theme/Material/MaterialThemeFileIconFactory.h @@ -3,6 +3,7 @@ #include "MaterialFolderIcon.h" #include "MaterialGenericFileIcon.h" #include "MaterialNdsFileIcon.h" +#include "MaterialThemeFileIcon.h" class MaterialColorScheme; class IFontRepository; @@ -29,6 +30,11 @@ public: return std::make_unique(name, _materialColorScheme, _fontRepository); } + std::unique_ptr CreateThemeFileIcon() const override + { + return std::make_unique(_materialColorScheme, _fontRepository); + } + private: const MaterialColorScheme* _materialColorScheme; const IFontRepository* _fontRepository; diff --git a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp index ec47070..a2dea5e 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp +++ b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.cpp @@ -27,11 +27,11 @@ #define WIDTH 209 #define HEIGHT 49 -#define LINE_WIDTH 160 +#define LINE_WIDTH 152 #define LINE_HEIGHT 16 -#define MAX_LINE_STRING_LENGTH 50 +#define MAX_LINE_STRING_LENGTH 128 -CustomBannerListItemView::CustomBannerListItemView(std::unique_ptr viewModel, +CustomBannerListItemView::CustomBannerListItemView(std::unique_ptr viewModel, const CustomThemeInfo* customThemeInfo, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository, u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset, diff --git a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h index d7814e4..c427c98 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h +++ b/arm9/source/romBrowser/Theme/custom/CustomBannerListItemView.h @@ -26,7 +26,7 @@ private: u32 _selectedTexVramOffset = 0; u32 _selectedPlttVramOffset = 0; - CustomBannerListItemView(std::unique_ptr viewModel, const CustomThemeInfo* customThemeInfo, + CustomBannerListItemView(std::unique_ptr viewModel, const CustomThemeInfo* customThemeInfo, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository, u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset, VBlankTextureLoader* vblankTextureLoader); diff --git a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp index 6a557ff..e9fd2ab 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp +++ b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.cpp @@ -7,11 +7,11 @@ CustomFileInfoView::CustomFileInfoView(const CustomThemeInfo* customThemeInfo, const IFontRepository* fontRepository) : _firstLine(Label2DView::CreateShared( - customThemeInfo->topBannerTextLine0Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Medium11))) + customThemeInfo->topBannerTextLine0Info.GetWidth(), 16, 128, fontRepository->GetFont(FontType::Medium11))) , _secondLine(Label2DView::CreateShared( - customThemeInfo->topBannerTextLine1Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10))) + customThemeInfo->topBannerTextLine1Info.GetWidth(), 16, 128, fontRepository->GetFont(FontType::Regular10))) , _thirdLine(Label2DView::CreateShared( - customThemeInfo->topBannerTextLine2Info.GetWidth(), 16, 50, fontRepository->GetFont(FontType::Regular10))) + customThemeInfo->topBannerTextLine2Info.GetWidth(), 16, 128, fontRepository->GetFont(FontType::Regular10))) , _filenameLabelView(Label2DView::CreateShared( customThemeInfo->topFileNameTextInfo.GetWidth(), 16, 256, fontRepository->GetFont(FontType::Medium7_5))) , _customThemeInfo(customThemeInfo) diff --git a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h index 8177783..6cce29a 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h +++ b/arm9/source/romBrowser/Theme/custom/CustomFileInfoView.h @@ -24,6 +24,15 @@ public: _firstLine->SetText(firstLine); } + void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, bool ellipsis) override + { + _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); + if (taskQueue) + _firstLine->SetTextAsync(taskQueue, firstLine); + else + _firstLine->SetText(firstLine); + } + void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override { _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); @@ -33,6 +42,14 @@ public: _firstLine->SetText(firstLine, length); } + void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine) override + { + if (taskQueue) + _secondLine->SetTextAsync(taskQueue, secondLine); + else + _secondLine->SetText(secondLine); + } + void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override { if (taskQueue) @@ -41,6 +58,14 @@ public: _secondLine->SetText(secondLine, length); } + void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine) override + { + if (taskQueue) + _thirdLine->SetTextAsync(taskQueue, thirdLine); + else + _thirdLine->SetText(thirdLine); + } + void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override { if (taskQueue) diff --git a/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h b/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h index eeb34e7..b9b7d74 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h +++ b/arm9/source/romBrowser/Theme/custom/CustomIconGridItemView.h @@ -22,7 +22,7 @@ private: u32 _selectedTexVramOffset; u32 _selectedPlttVramOffset; - CustomIconGridItemView(std::unique_ptr viewModel, const CustomThemeInfo* customThemeInfo, + CustomIconGridItemView(std::unique_ptr viewModel, const CustomThemeInfo* customThemeInfo, u32 texVramOffset, u32 plttVramOffset, u32 selectedTexVramOffset, u32 selectedPlttVramOffset) : IconGridItemView(std::move(viewModel)), _customThemeInfo(customThemeInfo), _texVramOffset(texVramOffset), _plttVramOffset(plttVramOffset) , _selectedTexVramOffset(selectedTexVramOffset), _selectedPlttVramOffset(selectedPlttVramOffset) { } diff --git a/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h b/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h index 6b32be5..f125cb2 100644 --- a/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h +++ b/arm9/source/romBrowser/Theme/custom/CustomRomBrowserViewFactory.h @@ -21,13 +21,13 @@ public: const IFontRepository* fontRepository) : _customThemeInfo(customThemeInfo), _materialColorScheme(materialColorScheme), _fontRepository(fontRepository) { } - SharedPtr CreateIconGridItemView(std::unique_ptr viewModel) const override + SharedPtr CreateIconGridItemView(std::unique_ptr viewModel) const override { return CustomIconGridItemView::CreateShared(std::move(viewModel), _customThemeInfo, _gridCellTexVramOffset, _gridCellPlttVramOffset, _gridCellSelectedTexVramOffset, _gridCellSelectedPlttVramOffset); } - SharedPtr CreateBannerListItemView(std::unique_ptr viewModel, + SharedPtr CreateBannerListItemView(std::unique_ptr viewModel, VBlankTextureLoader* vblankTextureLoader) const override { return CustomBannerListItemView::CreateShared(std::move(viewModel), _customThemeInfo, _materialColorScheme, _fontRepository, diff --git a/arm9/source/romBrowser/viewModels/DisplaySettingsViewModel.h b/arm9/source/romBrowser/viewModels/DisplaySettingsViewModel.h index cab9854..ba6b10a 100644 --- a/arm9/source/romBrowser/viewModels/DisplaySettingsViewModel.h +++ b/arm9/source/romBrowser/viewModels/DisplaySettingsViewModel.h @@ -43,6 +43,11 @@ public: _romBrowserController->HideDisplaySettings(); } + void GotoSettingsScreen() + { + _romBrowserController->GotoSettingsScreen(); + } + private: IRomBrowserController* _romBrowserController; RomBrowserDisplaySettings _romBrowserDisplaySettings; diff --git a/arm9/source/romBrowser/viewModels/IRomBrowserItemViewModel.h b/arm9/source/romBrowser/viewModels/IRomBrowserItemViewModel.h new file mode 100644 index 0000000..dd9c7bf --- /dev/null +++ b/arm9/source/romBrowser/viewModels/IRomBrowserItemViewModel.h @@ -0,0 +1,18 @@ +#pragma once +#include "core/task/TaskQueue.h" + +class IRomBrowserItemViewModel +{ +public: + virtual ~IRomBrowserItemViewModel() = default; + + virtual void Activate() = 0; + virtual void ShowGameInfo() = 0; + virtual void SetIndex(int index) = 0; + virtual void SetQueueTask(QueueTask queueTask) = 0; + virtual void CancelQueueTask() = 0; + virtual void DisposeQueueTaskWhenComplete() = 0; + +protected: + IRomBrowserItemViewModel() = default; +}; diff --git a/arm9/source/romBrowser/viewModels/RomBrowserBottomScreenViewModel.h b/arm9/source/romBrowser/viewModels/RomBrowserBottomScreenViewModel.h index 38b779f..bcfd982 100644 --- a/arm9/source/romBrowser/viewModels/RomBrowserBottomScreenViewModel.h +++ b/arm9/source/romBrowser/viewModels/RomBrowserBottomScreenViewModel.h @@ -20,7 +20,8 @@ public: return state == RomBrowserState::Browser || state == RomBrowserState::GameInfo || state == RomBrowserState::DisplaySettings - || state == RomBrowserState::Launching; + || state == RomBrowserState::Launching + || state == RomBrowserState::GoingToSettingsScreen; } const SharedPtr& GetRomBrowserViewModel() diff --git a/arm9/source/romBrowser/viewModels/RomBrowserItemViewModel.h b/arm9/source/romBrowser/viewModels/RomBrowserItemViewModel.h index dcdbf72..2f118e0 100644 --- a/arm9/source/romBrowser/viewModels/RomBrowserItemViewModel.h +++ b/arm9/source/romBrowser/viewModels/RomBrowserItemViewModel.h @@ -1,33 +1,33 @@ #pragma once -#include "core/task/TaskQueue.h" +#include "IRomBrowserItemViewModel.h" class IRomBrowserController; -class RomBrowserItemViewModel +class RomBrowserItemViewModel : public IRomBrowserItemViewModel { public: explicit RomBrowserItemViewModel(IRomBrowserController* romBrowserController) : _romBrowserController(romBrowserController) { } - void Activate(); - void ShowGameInfo(); + void Activate() override; + void ShowGameInfo() override; - void SetIndex(int index) + void SetIndex(int index) override { _index = index; } - void SetQueueTask(QueueTask queueTask) + void SetQueueTask(QueueTask queueTask) override { _queueTask = std::move(queueTask); } - void CancelQueueTask() + void CancelQueueTask() override { _queueTask.CancelTask(); } - void DisposeQueueTaskWhenComplete() + void DisposeQueueTaskWhenComplete() override { if (_queueTask.GetTask().IsCompleted()) { diff --git a/arm9/source/romBrowser/viewModels/RomBrowserViewModel.cpp b/arm9/source/romBrowser/viewModels/RomBrowserViewModel.cpp index 8784931..6ea7b25 100644 --- a/arm9/source/romBrowser/viewModels/RomBrowserViewModel.cpp +++ b/arm9/source/romBrowser/viewModels/RomBrowserViewModel.cpp @@ -31,7 +31,7 @@ RomBrowserViewModel::RomBrowserViewModel(IRomBrowserController* romBrowserContro } u64 startTick = gTickCounter.GetValue(); const auto& sdFolder = romBrowserController->GetSdFolder(); - int filteredCount; + u32 filteredCount; auto sortedFilteredFiles = sdFolder.FilterAndSort(filterSortParams, filteredCount); u64 endTick = gTickCounter.GetValue(); LOG_DEBUG("Filter + sort took: %d us\n", (u32)TickCounter::TicksToMicroSeconds(endTick - startTick)); diff --git a/arm9/source/romBrowser/views/BannerListItemView.cpp b/arm9/source/romBrowser/views/BannerListItemView.cpp index b6987e8..0fab37c 100644 --- a/arm9/source/romBrowser/views/BannerListItemView.cpp +++ b/arm9/source/romBrowser/views/BannerListItemView.cpp @@ -4,7 +4,7 @@ #include "gui/input/InputProvider.h" #include "BannerListItemView.h" -BannerListItemView::BannerListItemView(std::unique_ptr viewModel, +BannerListItemView::BannerListItemView(std::unique_ptr viewModel, SharedPtr firstLine, SharedPtr secondLine, SharedPtr thirdLine) : _viewModel(std::move(viewModel)) , _firstLine(std::move(firstLine)) @@ -21,6 +21,19 @@ void BannerListItemView::Update() { _viewModel->DisposeQueueTaskWhenComplete(); + if (IsFocused()) + { + _firstLine->SetEllipsisStyle(LabelView::EllipsisStyle::Marquee); + _secondLine->SetEllipsisStyle(LabelView::EllipsisStyle::Marquee); + _thirdLine->SetEllipsisStyle(LabelView::EllipsisStyle::Marquee); + } + else + { + _firstLine->SetEllipsisStyle(LabelView::EllipsisStyle::Ellipsis); + _secondLine->SetEllipsisStyle(LabelView::EllipsisStyle::Ellipsis); + _thirdLine->SetEllipsisStyle(LabelView::EllipsisStyle::Ellipsis); + } + ViewContainer::Update(); if (_icon) diff --git a/arm9/source/romBrowser/views/BannerListItemView.h b/arm9/source/romBrowser/views/BannerListItemView.h index f7f3993..79df058 100644 --- a/arm9/source/romBrowser/views/BannerListItemView.h +++ b/arm9/source/romBrowser/views/BannerListItemView.h @@ -2,7 +2,7 @@ #include "BannerView.h" #include "gui/views/LabelView.h" #include "../FileType/FileIcon.h" -#include "romBrowser/viewModels/RomBrowserItemViewModel.h" +#include "romBrowser/viewModels/IRomBrowserItemViewModel.h" #include "RomBrowserItemInputHandler.h" class BannerListItemView : public BannerView @@ -39,6 +39,15 @@ public: _firstLine->SetText(firstLine); } + void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, bool ellipsis) override + { + _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); + if (taskQueue) + _firstLine->SetTextAsync(taskQueue, firstLine); + else + _firstLine->SetText(firstLine); + } + void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) override { _firstLine->SetEllipsisStyle(ellipsis ? LabelView::EllipsisStyle::Ellipsis : LabelView::EllipsisStyle::None); @@ -48,6 +57,14 @@ public: _firstLine->SetText(firstLine, length); } + void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine) override + { + if (taskQueue) + _secondLine->SetTextAsync(taskQueue, secondLine); + else + _secondLine->SetText(secondLine); + } + void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) override { if (taskQueue) @@ -56,6 +73,14 @@ public: _secondLine->SetText(secondLine, length); } + void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine) override + { + if (taskQueue) + _thirdLine->SetTextAsync(taskQueue, thirdLine); + else + _thirdLine->SetText(thirdLine); + } + void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) override { if (taskQueue) @@ -64,18 +89,18 @@ public: _thirdLine->SetText(thirdLine, length); } - RomBrowserItemViewModel& GetViewModel() const + IRomBrowserItemViewModel& GetViewModel() const { return *_viewModel; } protected: - std::unique_ptr _viewModel; + std::unique_ptr _viewModel; SharedPtr _firstLine; SharedPtr _secondLine; SharedPtr _thirdLine; RomBrowserItemInputHandler _inputHandler; - BannerListItemView(std::unique_ptr viewModel, SharedPtr firstLine, + BannerListItemView(std::unique_ptr viewModel, SharedPtr firstLine, SharedPtr secondLine, SharedPtr thirdLine); }; diff --git a/arm9/source/romBrowser/views/BannerView.h b/arm9/source/romBrowser/views/BannerView.h index 93bb97f..d7a6356 100644 --- a/arm9/source/romBrowser/views/BannerView.h +++ b/arm9/source/romBrowser/views/BannerView.h @@ -42,12 +42,15 @@ public: protected: std::unique_ptr _icon = nullptr; - vu16* _iconVram; - u32 _iconVramOffset; - u32 _lines; + vu16* _iconVram = nullptr; + u32 _iconVramOffset = 0; + u32 _lines = 3; virtual void SetFirstLineAsync(TaskQueueBase* taskQueue, const char* firstLine, bool ellipsis) = 0; + virtual void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, bool ellipsis) = 0; virtual void SetFirstLineAsync(TaskQueueBase* taskQueue, const char16_t* firstLine, u32 length, bool ellipsis) = 0; + virtual void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine) = 0; virtual void SetSecondLineAsync(TaskQueueBase* taskQueue, const char16_t* secondLine, u32 length) = 0; + virtual void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine) = 0; virtual void SetThirdLineAsync(TaskQueueBase* taskQueue, const char16_t* thirdLine, u32 length) = 0; }; diff --git a/arm9/source/romBrowser/views/CoverView.h b/arm9/source/romBrowser/views/CoverView.h index 7213274..1157917 100644 --- a/arm9/source/romBrowser/views/CoverView.h +++ b/arm9/source/romBrowser/views/CoverView.h @@ -4,7 +4,7 @@ #include "gui/views/View.h" #include "../FileType/FileCover.h" #include "gui/VBlankTextureLoader.h" -#include "romBrowser/viewModels/RomBrowserItemViewModel.h" +#include "romBrowser/viewModels/IRomBrowserItemViewModel.h" #include "RomBrowserItemInputHandler.h" class CoverView : public View @@ -46,13 +46,13 @@ public: void UploadCoverGraphics(); - RomBrowserItemViewModel& GetViewModel() const + IRomBrowserItemViewModel& GetViewModel() const { return *_viewModel; } private: - std::unique_ptr _viewModel; + std::unique_ptr _viewModel; VBlankTextureLoader* _vblankTextureLoader; AtomicSharedPtr _cover; VBlankTextureLoadRequest _textureLoadRequest; @@ -60,7 +60,7 @@ private: u32 _plttVramOffset = 0; RomBrowserItemInputHandler _inputHandler; - CoverView(std::unique_ptr viewModel, VBlankTextureLoader* vblankTextureLoader) + CoverView(std::unique_ptr viewModel, VBlankTextureLoader* vblankTextureLoader) : _viewModel(std::move(viewModel)), _vblankTextureLoader(vblankTextureLoader) , _inputHandler(this, _viewModel.get()) { } }; diff --git a/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.cpp b/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.cpp index 3de9fab..4d22208 100644 --- a/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.cpp +++ b/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.cpp @@ -15,6 +15,7 @@ #include "moviesIcon.h" #include "unknownIcon.h" #include "coverflowIcon.h" +#include "themeIcon.h" #include "../IRomBrowserController.h" #include "gui/input/InputProvider.h" #include "themes/material/MaterialColorScheme.h" @@ -24,6 +25,9 @@ #define TITLE_LABEL_X 20 #define TITLE_LABEL_Y 16 +#define THEME_BUTTON_X 212 +#define THEME_BUTTON_Y (TITLE_LABEL_Y - 7) + #define LAYOUT_LABEL_X 20 #define LAYOUT_LABEL_Y 46 @@ -53,19 +57,28 @@ DisplaySettingsBottomSheetView::DisplaySettingsBottomSheetView( const IFontRepository* fontRepository) : _viewModel(viewModel) , _titleLabel(Label2DView::CreateShared(128, 16, 25, fontRepository->GetFont(FontType::Medium11))) + , _themeButton(IconButton2DView::CreateShared( + IconButtonView::Type::Standard, + IconButtonView::State::NoToggle, + md::sys::color::inverseOnSurface, + materialColorScheme)) , _layoutLabel(Label2DView::CreateShared(64, 16, 25, fontRepository->GetFont(FontType::Regular10))) , _sortingLabel(Label2DView::CreateShared(64, 16, 25, fontRepository->GetFont(FontType::Regular10))) , _materialColorScheme(materialColorScheme) - // , _filtersLabel(64, 16, 25, fontRepository->GetFont(FontType::Regular10)) { _titleLabel->SetText(u"Display Settings"); AddChildTail(_titleLabel.GetPointer()); + + _themeButton->SetAction([] (IconButtonView*, void* arg) + { + ((DisplaySettingsBottomSheetView*)arg)->_viewModel->GotoSettingsScreen(); + }, this); + AddChildTail(_themeButton.GetPointer()); + _layoutLabel->SetText(u"Layout"); AddChildTail(_layoutLabel.GetPointer()); _sortingLabel->SetText(u"Sorting"); AddChildTail(_sortingLabel.GetPointer()); - // _filtersLabel.SetText(u"Filters"); - // AddChildTail(&_filtersLabel); for (auto& layoutOption : _layoutOptions) { @@ -78,14 +91,6 @@ DisplaySettingsBottomSheetView::DisplaySettingsBottomSheetView( sortOption = CreateSortOptionIconButton(); AddChildTail(sortOption.GetPointer()); } - - // for (auto& filterOption : _filterOptions) - // { - // filterOption = CreateFilterOptionIconButton(); - // AddChildTail(&filterOption); - // } - - // _filterOptions[0].SetState(IconButtonView::State::ToggleSelected); } SharedPtr DisplaySettingsBottomSheetView::CreateLayoutOptionIconButton() @@ -134,18 +139,6 @@ SharedPtr DisplaySettingsBottomSheetView::CreateSortOptionIcon return sortOption; } -// IconButtonView DisplaySettingsBottomSheetView::CreateFilterOptionIconButton() -// { -// IconButtonView filterOption -// { -// IconButtonView::Type::Tonal, -// IconButtonView::State::ToggleUnselected, -// md::sys::color::surfaceContainerLow, -// _materialColorScheme -// }; -// return filterOption; -// } - void DisplaySettingsBottomSheetView::InitVram(const VramContext& vramContext) { BottomSheetView::InitVram(vramContext); @@ -153,6 +146,8 @@ void DisplaySettingsBottomSheetView::InitVram(const VramContext& vramContext) const auto objVramManager = vramContext.GetObjVramManager(); if (objVramManager) { + _themeButton->SetIconVramOffset(LoadIcon(*objVramManager, themeIconTiles, themeIconTilesLen)); + // layout options _layoutOptions[0]->SetIconVramOffset(LoadIcon(*objVramManager, hGridIconTiles, hGridIconTilesLen)); _layoutOptions[1]->SetIconVramOffset(LoadIcon(*objVramManager, vGridIconTiles, vGridIconTilesLen)); @@ -162,14 +157,6 @@ void DisplaySettingsBottomSheetView::InitVram(const VramContext& vramContext) // sort options _sortOptions[0]->SetIconVramOffset(LoadIcon(*objVramManager, sortNameAscendingIconTiles, sortNameAscendingIconTilesLen)); _sortOptions[1]->SetIconVramOffset(LoadIcon(*objVramManager, sortNameDescendingIconTiles, sortNameDescendingIconTilesLen)); - // _sortOptions[2].SetIconVramOffset(LoadIcon(objVramManager, recentIconTiles, recentIconTilesLen)); - - // filter options - // _filterOptions[0].SetIconVramOffset(LoadIcon(objVramManager, gamesIconTiles, gamesIconTilesLen)); - // _filterOptions[1].SetIconVramOffset(LoadIcon(objVramManager, picturesIconTiles, picturesIconTilesLen)); - // _filterOptions[2].SetIconVramOffset(LoadIcon(objVramManager, musicIconTiles, musicIconTilesLen)); - // _filterOptions[3].SetIconVramOffset(LoadIcon(objVramManager, moviesIconTiles, moviesIconTilesLen)); - // _filterOptions[4].SetIconVramOffset(LoadIcon(objVramManager, unknownIconTiles, unknownIconTilesLen)); } } @@ -178,12 +165,12 @@ void DisplaySettingsBottomSheetView::UpdateLabels() _titleLabel->SetPosition(TITLE_LABEL_X, _position.y + TITLE_LABEL_Y); _layoutLabel->SetPosition(LAYOUT_LABEL_X, _position.y + LAYOUT_LABEL_Y); _sortingLabel->SetPosition(SORTING_LABEL_X, _position.y + SORTING_LABEL_Y); - // _filtersLabel.SetPosition(FILTERS_LABEL_X, _position.y + FILTERS_LABEL_Y); } void DisplaySettingsBottomSheetView::Update() { BottomSheetView::Update(); + _themeButton->SetPosition(THEME_BUTTON_X, _position.y + THEME_BUTTON_Y); UpdateLabels(); auto selectedDisplayMode = _viewModel->GetRomBrowserDisplayMode(); int x = 70; @@ -209,12 +196,6 @@ void DisplaySettingsBottomSheetView::Update() x += 32; idx++; } - // x = 70; - // for (auto& filterOption : _filterOptions) - // { - // filterOption.SetPosition(x, _position.y + 102); - // x += 32; - // } } void DisplaySettingsBottomSheetView::Draw(GraphicsContext& graphicsContext) @@ -228,8 +209,6 @@ void DisplaySettingsBottomSheetView::Draw(GraphicsContext& graphicsContext) _layoutLabel->SetForegroundColor(_materialColorScheme->onSurfaceVariant); _sortingLabel->SetBackgroundColor(_materialColorScheme->GetColor(md::sys::color::surfaceContainerLow)); _sortingLabel->SetForegroundColor(_materialColorScheme->onSurfaceVariant); - // _filtersLabel.SetBackgroundColor(_materialColorScheme->GetColor(md::sys::color::surfaceContainerLow)); - // _filtersLabel.SetForegroundColor(_materialColorScheme->onSurfaceVariant); BottomSheetView::Draw(graphicsContext); } graphicsContext.SetPriority(oldPrio); @@ -250,6 +229,18 @@ bool DisplaySettingsBottomSheetView::HandleInput( SharedPtr DisplaySettingsBottomSheetView::MoveFocus(const SharedPtr& currentFocus, FocusMoveDirection direction, View* source) { + if (currentFocus.GetPointer() == _themeButton.GetPointer()) + { + if (direction == FocusMoveDirection::Down) + { + return _layoutOptions[0]; + } + else + { + return nullptr; + } + } + int idx = 0; for (auto& layoutOption : _layoutOptions) { @@ -267,12 +258,10 @@ SharedPtr DisplaySettingsBottomSheetView::MoveFocus(const SharedPtr& idx = 0; return _layoutOptions[idx]; } - // else if (direction == FocusMoveDirection::Up) - // { - // if (idx >= (int)_filterOptions.size()) - // idx = _filterOptions.size() - 1; - // return &_filterOptions[idx]; - // } + else if (direction == FocusMoveDirection::Up) + { + return _themeButton; + } else //if (direction == FocusMoveDirection::Down) { if (idx >= (int)_sortOptions.size()) @@ -299,59 +288,22 @@ SharedPtr DisplaySettingsBottomSheetView::MoveFocus(const SharedPtr& idx = 0; return _sortOptions[idx]; } - else //if (direction == FocusMoveDirection::Up) + else if (direction == FocusMoveDirection::Up) { if (idx >= (int)_layoutOptions.size()) idx = _layoutOptions.size() - 1; return _layoutOptions[idx]; } - // else //if (direction == FocusMoveDirection::Down) - // { - // if (idx >= (int)_filterOptions.size()) - // idx = _filterOptions.size() - 1; - // return &_filterOptions[idx]; - // } } idx++; } - // idx = 0; - // for (auto& filterOption : _filterOptions) - // { - // if (currentFocus == &filterOption) - // { - // if (direction == FocusMoveDirection::Left) - // { - // if (--idx < 0) - // idx += _filterOptions.size(); - // return &_filterOptions[idx]; - // } - // else if (direction == FocusMoveDirection::Right) - // { - // if (++idx >= (int)_filterOptions.size()) - // idx = 0; - // return &_filterOptions[idx]; - // } - // else if (direction == FocusMoveDirection::Up) - // { - // if (idx >= (int)_sortOptions.size()) - // idx = _sortOptions.size() - 1; - // return &_sortOptions[idx]; - // } - // else //if (direction == FocusMoveDirection::Down) - // { - // if (idx >= (int)_layoutOptions.size()) - // idx = _layoutOptions.size() - 1; - // return &_layoutOptions[idx]; - // } - // } - // idx++; - // } return nullptr; } void DisplaySettingsBottomSheetView::SetGraphics( const IconButton2DView::VramToken& iconButtonVramToken) { + _themeButton->SetGraphics(iconButtonVramToken); for (auto& layoutOption : _layoutOptions) { layoutOption->SetGraphics(iconButtonVramToken); @@ -360,8 +312,6 @@ void DisplaySettingsBottomSheetView::SetGraphics( { sortOption->SetGraphics(iconButtonVramToken); } - // for (auto& filterOption : _filterOptions) - // filterOption.SetGraphics(iconButtonVramToken); } void DisplaySettingsBottomSheetView::Close() diff --git a/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.h b/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.h index f92d7a2..2699620 100644 --- a/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.h +++ b/arm9/source/romBrowser/views/DisplaySettingsBottomSheetView.h @@ -35,19 +35,17 @@ private: DisplaySettingsViewModel* _viewModel; SharedPtr _titleLabel; + SharedPtr _themeButton; SharedPtr _layoutLabel; SharedPtr _sortingLabel; - // LabelView _filtersLabel; std::array, 4> _layoutOptions; std::array, /*3*/2> _sortOptions; - // std::array _filterOptions; const MaterialColorScheme* _materialColorScheme; SharedPtr CreateLayoutOptionIconButton(); SharedPtr CreateSortOptionIconButton(); - // IconButton2DView CreateFilterOptionIconButton(); DisplaySettingsBottomSheetView(DisplaySettingsViewModel* viewModel, const MaterialColorScheme* materialColorScheme, const IFontRepository* fontRepository); diff --git a/arm9/source/romBrowser/views/IconGridItemView.h b/arm9/source/romBrowser/views/IconGridItemView.h index 7d80a12..66286f3 100644 --- a/arm9/source/romBrowser/views/IconGridItemView.h +++ b/arm9/source/romBrowser/views/IconGridItemView.h @@ -1,6 +1,6 @@ #pragma once #include -#include "romBrowser/viewModels/RomBrowserItemViewModel.h" +#include "romBrowser/viewModels/IRomBrowserItemViewModel.h" #include "gui/views/View.h" #include "../FileType/FileIcon.h" #include "RomBrowserItemInputHandler.h" @@ -50,18 +50,18 @@ public: virtual void SetGraphics(const VramToken& vramToken) { } - RomBrowserItemViewModel& GetViewModel() const + IRomBrowserItemViewModel& GetViewModel() const { return *_viewModel; } protected: - std::unique_ptr _viewModel; + std::unique_ptr _viewModel; std::unique_ptr _icon; vu16* _iconVram; u32 _iconVramOffset; RomBrowserItemInputHandler _inputHandler; - explicit IconGridItemView(std::unique_ptr viewModel) + explicit IconGridItemView(std::unique_ptr viewModel) : _viewModel(std::move(viewModel)), _inputHandler(this, _viewModel.get()) { } }; diff --git a/arm9/source/romBrowser/views/RomBrowserItemInputHandler.cpp b/arm9/source/romBrowser/views/RomBrowserItemInputHandler.cpp index 0a55296..1798efe 100644 --- a/arm9/source/romBrowser/views/RomBrowserItemInputHandler.cpp +++ b/arm9/source/romBrowser/views/RomBrowserItemInputHandler.cpp @@ -2,7 +2,7 @@ #include "gui/FocusManager.h" #include "gui/input/InputProvider.h" #include "gui/views/View.h" -#include "romBrowser/viewModels/RomBrowserItemViewModel.h" +#include "romBrowser/viewModels/IRomBrowserItemViewModel.h" #include "RomBrowserItemInputHandler.h" #define LONG_PRESS_FRAMES 30 diff --git a/arm9/source/romBrowser/views/RomBrowserItemInputHandler.h b/arm9/source/romBrowser/views/RomBrowserItemInputHandler.h index cc3be78..d491383 100644 --- a/arm9/source/romBrowser/views/RomBrowserItemInputHandler.h +++ b/arm9/source/romBrowser/views/RomBrowserItemInputHandler.h @@ -3,13 +3,13 @@ class InputProvider; class FocusManager; -class RomBrowserItemViewModel; +class IRomBrowserItemViewModel; class View; class RomBrowserItemInputHandler { public: - RomBrowserItemInputHandler(View* view, RomBrowserItemViewModel* viewModel) + RomBrowserItemInputHandler(View* view, IRomBrowserItemViewModel* viewModel) : _view(view), _viewModel(viewModel) { } bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager); @@ -21,7 +21,7 @@ public: private: View* _view; - RomBrowserItemViewModel* _viewModel; + IRomBrowserItemViewModel* _viewModel; bool _penDown = false; int _penDownFrames = 0; }; diff --git a/arm9/source/services/process/ProcessFactory.thumb.cpp b/arm9/source/services/process/ProcessFactory.thumb.cpp index 67ee9bd..cef570f 100644 --- a/arm9/source/services/process/ProcessFactory.thumb.cpp +++ b/arm9/source/services/process/ProcessFactory.thumb.cpp @@ -6,6 +6,7 @@ #include "bgm/BgmService.h" #include "App.h" #include "PicoLoaderProcess.h" +#include "settings/SettingsProcess.h" #include "ProcessFactory.h" namespace di = boost::di; @@ -35,3 +36,4 @@ static auto diConfig = [] { return di::make_injector( REGISTER_PROCESS(App); REGISTER_PROCESS(PicoLoaderProcess); +REGISTER_PROCESS(SettingsProcess); diff --git a/arm9/source/settings/ISettingsController.h b/arm9/source/settings/ISettingsController.h new file mode 100644 index 0000000..d64f067 --- /dev/null +++ b/arm9/source/settings/ISettingsController.h @@ -0,0 +1,18 @@ +#pragma once +class TaskQueueBase; +class ThemeInfoManager; +class ThemeRepository; + +class ISettingsController +{ +public: + virtual ~ISettingsController() = default; + + virtual void Initialize() = 0; + virtual void NavigateUp() = 0; + virtual void SelectTheme(const char* themeFolderName) = 0; + + virtual ThemeInfoManager& GetThemeInfoManager() const = 0; + virtual const ThemeRepository& GetThemeRepository() const = 0; + virtual TaskQueueBase* GetIoTaskQueue() const = 0; +}; diff --git a/arm9/source/settings/SettingsController.cpp b/arm9/source/settings/SettingsController.cpp new file mode 100644 index 0000000..ecfe19c --- /dev/null +++ b/arm9/source/settings/SettingsController.cpp @@ -0,0 +1,28 @@ +#include "common.h" +#include "App.h" +#include "SettingsController.h" + +SettingsController::SettingsController(IAppSettingsService* appSettingsService, TaskQueueBase* ioTaskQueue) + : _appSettingsService(appSettingsService), _ioTaskQueue(ioTaskQueue) { } + +void SettingsController::Initialize() +{ + _themeRepository.Initialize(); + _themeInfoManager = std::make_unique(_themeRepository); +} + +void SettingsController::NavigateUp() +{ + gProcessManager.Goto(); +} + +void SettingsController::SelectTheme(const char* themeFolderName) +{ + _appSettingsService->GetAppSettings().theme = themeFolderName; + _ioTaskQueue->Enqueue([this] (const vu8& cancelRequested) + { + _appSettingsService->Save(); + return TaskResult::Completed(); + }); + gProcessManager.Goto(); +} diff --git a/arm9/source/settings/SettingsController.h b/arm9/source/settings/SettingsController.h new file mode 100644 index 0000000..349bc29 --- /dev/null +++ b/arm9/source/settings/SettingsController.h @@ -0,0 +1,26 @@ +#pragma once +#include "ISettingsController.h" +#include "ThemeInfoManager.h" +#include "themes/ThemeRepository.h" + +class IAppSettingsService; + +class SettingsController : public ISettingsController +{ +public: + SettingsController(IAppSettingsService* appSettingsService, TaskQueueBase* ioTaskQueue); + + void Initialize() override; + void NavigateUp() override; + void SelectTheme(const char* themeFolderName) override; + + ThemeInfoManager& GetThemeInfoManager() const override { return *_themeInfoManager; } + const ThemeRepository& GetThemeRepository() const override { return _themeRepository; } + TaskQueueBase* GetIoTaskQueue() const override { return _ioTaskQueue; } + +private: + IAppSettingsService* _appSettingsService; + TaskQueueBase* _ioTaskQueue; + ThemeRepository _themeRepository; + std::unique_ptr _themeInfoManager; +}; diff --git a/arm9/source/settings/SettingsProcess.cpp b/arm9/source/settings/SettingsProcess.cpp new file mode 100644 index 0000000..64e4e68 --- /dev/null +++ b/arm9/source/settings/SettingsProcess.cpp @@ -0,0 +1,307 @@ +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include "core/math/RgbMixer.h" +#include "gui/GraphicsContext.h" +#include "gui/Gx.h" +#include "settings/viewModels/ThemeListViewModel.h" +#include "themes/ThemeInfoFactory.h" +#include "themes/ThemeFactory.h" +#include "SettingsProcess.h" + +SettingsProcess::SettingsProcess(IAppSettingsService& appSettingsService) + : _mainObjPltt(GFX_PLTT_OBJ_MAIN) + , _mainObjVram(GFX_OBJ_MAIN) + , _subObjVram(GFX_OBJ_SUB) + , _textureVram((vu16*)0x06860000) + , _texturePaletteVram((vu16*)0x6880000) + , _mainVramContext(nullptr, &_mainObjVram, &_textureVram, &_texturePaletteVram) + , _subVramContext(nullptr, &_subObjVram, nullptr, nullptr) + , _appSettingsService(appSettingsService) + , _inputProvider(&_keyInputSource, &_touchInputSource) + , _inputRepeater(&_inputProvider, + InputKey::DpadLeft | InputKey::DpadRight | InputKey::DpadUp | InputKey::DpadDown | InputKey::L | InputKey::R, + 25, 8) { } + +void SettingsProcess::Run() +{ + InitVramMapping(); + gx_init(); + + _chipViewVram = ChipView::UploadGraphics(_mainObjVram); + _iconButtonViewVram = IconButton2DView::UploadGraphics(_mainObjVram); + + mem_setVramEMapping(MEM_VRAM_E_LCDC); + _rgb6Palette.UploadGraphics(_mainVramContext); + mem_setVramEMapping(MEM_VRAM_E_TEX_PLTT_SLOT_0123); + + LoadTheme(); + + _settingsController = std::make_unique(&_appSettingsService, &_ioTaskQueue); + _settingsController->Initialize(); + + auto viewModel = SharedPtr::MakeShared(_settingsController.get()); + _themeListBottomView = ThemeListBottomView::CreateShared(viewModel, + &_theme->GetMaterialColorScheme(), _theme->GetRomBrowserViewFactory(), + _theme->GetThemeFileIconFactory(), &_vblankTextureLoader); + _themeListBottomView->InitVram(_mainVramContext); + _themeListBottomView->Focus(_focusManager); + + _themeListTopView = ThemeListTopView::CreateShared(viewModel, &_theme->GetMaterialColorScheme(), _theme->GetFontRepository()); + _themeListTopView->InitVram(_subVramContext); + + _ioTaskQueue.StartThread(1, _ioTaskThreadStack, sizeof(_ioTaskThreadStack)); + + const auto& materialColorScheme = _theme->GetMaterialColorScheme(); + + auto scrimBlendColor = Rgb<8, 8, 8>( + materialColorScheme.inverseOnSurface.r + (materialColorScheme.scrim.r - materialColorScheme.inverseOnSurface.r) * 5 / 16, + materialColorScheme.inverseOnSurface.g + (materialColorScheme.scrim.g - materialColorScheme.inverseOnSurface.g) * 5 / 16, + materialColorScheme.inverseOnSurface.b + (materialColorScheme.scrim.b - materialColorScheme.inverseOnSurface.b) * 5 / 16); + + RgbMixer::MakeGradientPalette((u16*)GFX_PLTT_BG_MAIN, scrimBlendColor, materialColorScheme.GetColor(md::sys::color::surfaceContainerLow)); + + GFX_PLTT_BG_MAIN[0] = ColorConverter::ToGBGR565(materialColorScheme.inverseOnSurface); + GFX_PLTT_BG_MAIN[31] = ColorConverter::ToGBGR565(materialColorScheme.scrim); + REG_DISPCNT = 0x21191B; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + REG_BG0CNT = 3; + REG_DISPCNT_SUB = 0x40211015; + GFX_PLTT_BG_SUB[0] = ColorConverter::ToGBGR565(materialColorScheme.inverseOnSurface); + + REG_DMA3FILL = 0; + dma_ntrSetParams(3, (const void*)®_DMA3FILL, GFX_BG_SUB, + DMACNT_ENABLE | DMACNT_MODE_IMMEDIATE | DMACNT_32BIT | + DMACNT_SRC_MODE_FIXED | DMACNT_DST_MODE_INCREMENT | + DMACNT_COUNT((256 * 192 * 2) >> 2)); + dma_ntrWait(3); + + Gx::MtxMode(GX_MTX_MODE_PROJECTION); + mtx43_t orthoMtx = + { + 2048, 0, 0, + 0, -21845, 0, + 0, 0, 4096 >> 5, + -4096, 4096, 0 + }; + Gx::MtxLoad43(&orthoMtx); + + _vcountIrqStarted = false; + rtos_disableIrqMask(RTOS_IRQ_VCOUNT); + rtos_setIrqFunc(RTOS_IRQ_VCOUNT, [] (u32 mask) { ((SettingsProcess*)gProcessManager.GetRunningProcess())->VCountIrq(); }); + + _fadeAnimator = Animator(16, 0, 16, &md::sys::motion::easing::linear); + + MainLoop(); + + rtos_disableIrqMask(RTOS_IRQ_VCOUNT); + rtos_setIrqFunc(RTOS_IRQ_VCOUNT, nullptr); +} + +void SettingsProcess::Exit() +{ + _fadeAnimator.Goto(16, 16, &md::sys::motion::easing::linear); + _exit = true; +} + +void SettingsProcess::InitVramMapping() const +{ + mem_setVramAMapping(MEM_VRAM_AB_TEX_SLOT_1); + mem_setVramBMapping(MEM_VRAM_AB_MAIN_OBJ_00000); + mem_setVramCMapping(MEM_VRAM_C_SUB_BG_00000); + mem_setVramDMapping(MEM_VRAM_D_TEX_SLOT_0); + mem_setVramEMapping(MEM_VRAM_E_TEX_PLTT_SLOT_0123); + mem_setVramFMapping(MEM_VRAM_FG_MAIN_BG_00000); + mem_setVramGMapping(MEM_VRAM_FG_MAIN_BG_04000); + mem_setVramHMapping(MEM_VRAM_H_SUB_BG_EXT_PLTT_SLOT_0123); + mem_setVramIMapping(MEM_VRAM_I_SUB_OBJ_00000); +} + +void SettingsProcess::LoadTheme() +{ + ThemeInfoFactory themeInfoFactory; + auto themeInfo = themeInfoFactory.CreateFromThemeFolder(_appSettingsService.GetAppSettings().theme); + if (!themeInfo) + { + LOG_DEBUG("Failed to load theme '%s'. Using fallback theme.\n", _appSettingsService.GetAppSettings().theme.GetString()); + themeInfo = themeInfoFactory.CreateFallbackTheme(); + } + _theme = ThemeFactory().CreateFromThemeInfo(themeInfo.get()); + themeInfo.reset(); + _theme->LoadRomBrowserResources(_mainVramContext, _subVramContext); + // _topBackground = _theme->CreateRomBrowserTopBackground(); + // _topBackground->LoadResources(*_theme, _subVramContext); + _bottomBackground = _theme->CreateRomBrowserBottomBackground(); + _bottomBackground->LoadResources(*_theme, _mainVramContext); +} + +void SettingsProcess::MainLoop() +{ + bool fadeIn = true; + while (true) + { + Update(); + Draw(); + VBlank::Wait(); + VBlank(); + if (_exit) + { + bool fadeComplete = _fadeAnimator.Update(); + REG_MASTER_BRIGHT = 0x4000 | _fadeAnimator.GetValue(); + REG_MASTER_BRIGHT_SUB = 0x4000 | _fadeAnimator.GetValue(); + if (fadeComplete) + { + break; + } + } + else if (fadeIn) + { + bool fadeComplete = _fadeAnimator.Update(); + if (fadeComplete) + { + fadeIn = false; + REG_BLDCNT_SUB = 0; + REG_MASTER_BRIGHT = 0; + REG_MASTER_BRIGHT_SUB = 0; + } + else + { + int fade = _fadeAnimator.GetValue(); + REG_MASTER_BRIGHT = 0x4000 | fade; + REG_MASTER_BRIGHT_SUB = 0x4000 | fade; + } + } + } +} + +void SettingsProcess::Update() +{ + if (!_exit) + { + HandleInput(); + } + + // if (_topBackground) + // { + // _topBackground->Update(); + // } + if (_bottomBackground) + { + _bottomBackground->Update(); + } + + _themeListBottomView->Update(); + _themeListTopView->Update(); +} + +void SettingsProcess::HandleInput() +{ + _focusManager.Update(_inputRepeater); + Point touchPoint; + if (_inputRepeater.Triggered(InputKey::Touch) && + _inputRepeater.GetCurrentTouchPoint(touchPoint)) + { + // pen down + _themeListBottomView->HandlePenDown(touchPoint, _focusManager); + _lastTouchPoint = touchPoint; + } + else if (_inputRepeater.Released(InputKey::Touch)) + { + // pen up + _themeListBottomView->HandlePenUp(_lastTouchPoint, _focusManager); + } + else if (_inputRepeater.Current(InputKey::Touch) + && _inputRepeater.GetCurrentTouchPoint(touchPoint)) + { + // pen move + _themeListBottomView->HandlePenMove(touchPoint, _focusManager); + _lastTouchPoint = touchPoint; + } +} + +void SettingsProcess::Draw() +{ + gx_reset(); + Gx::Viewport(0, 0, 255, 191); + Gx::MtxMode(GX_MTX_MODE_POSITION_VECTOR); + Gx::MtxIdentity(); + + GraphicsContext mainGraphicsContext + { + &_mainOam, + &_mainObjPltt, + &_rgb6Palette + }; + GraphicsContext subGraphicsContext + { + &_subOam, + &_subObjPltt, + nullptr + }; + + _mainOam.Clear(); + _subOam.Clear(); + _mainObjPltt.Reset(); + _subObjPltt.Reset(); + mainGraphicsContext.SetPriority(3); + subGraphicsContext.SetPriority(2); + + // if (_topBackground) + // { + // _topBackground->Draw(subGraphicsContext); + // } + if (_bottomBackground) + { + _bottomBackground->Draw(mainGraphicsContext); + } + + _themeListBottomView->Draw(mainGraphicsContext); + _themeListTopView->Draw(subGraphicsContext); + + _mainObjPltt.EndOfFrame(); + + Gx::SwapBuffers(GX_XLU_SORT_MANUAL, GX_DEPTH_MODE_Z); +} + +void SettingsProcess::VBlank() +{ + dma_ntrStopDirect(0); // stop hblank dma + _inputProvider.Sample(); + _inputRepeater.Update(); + _mainOam.Apply(GFX_OAM_MAIN); + _subOam.Apply(GFX_OAM_SUB); + _subObjPltt.Apply(GFX_PLTT_OBJ_SUB); + + if (!_vcountIrqStarted) + { + rtos_ackIrqMask(RTOS_IRQ_VCOUNT); + rtos_enableIrqMask(RTOS_IRQ_VCOUNT); + _vcountIrqStarted = true; + } + _mainObjPltt.VBlank(); + + // if (_topBackground) + // { + // _topBackground->VBlank(); + // } + if (_bottomBackground) + { + _bottomBackground->VBlank(); + } + + _themeListBottomView->VBlank(); + _vblankTextureLoader.VBlank(); + + _themeListTopView->VBlank(); +} + +void SettingsProcess::VCountIrq() +{ + _mainObjPltt.VCount(); +} diff --git a/arm9/source/settings/SettingsProcess.h b/arm9/source/settings/SettingsProcess.h new file mode 100644 index 0000000..f51aafa --- /dev/null +++ b/arm9/source/settings/SettingsProcess.h @@ -0,0 +1,86 @@ +#pragma once +#include +#include "SettingsController.h" +#include "animation/Animator.h" +#include "core/task/TaskQueue.h" +#include "gui/AdvancedPaletteManager.h" +#include "gui/AscendingStackVramManager.h" +#include "gui/OamManager.h" +#include "gui/Rgb6Palette.h" +#include "gui/SimplePaletteManager.h" +#include "gui/VBlankTextureLoader.h" +#include "gui/VramContext.h" +#include "gui/input/InputRepeater.h" +#include "gui/input/PadInputSource.h" +#include "gui/input/SampledInputProvider.h" +#include "gui/input/TouchInputSource.h" +#include "romBrowser/views/ChipView.h" +#include "romBrowser/views/IconButton2DView.h" +#include "settings/views/ThemeListTopView.h" +#include "settings/views/ThemeListBottomView.h" +#include "themes/ITheme.h" +#include "services/process/IProcess.h" +#include "services/settings/IAppSettingsService.h" + +class SettingsController; + +class alignas(32) SettingsProcess : public IProcess +{ +public: + SettingsProcess(IAppSettingsService& appSettingsService); + + void Run() override; + void Exit() override; + +private: + AdvancedPaletteManager<64> _mainObjPltt; + OamManager _mainOam; + AscendingStackVramManager _mainObjVram; + OamManager _subOam; + SimplePaletteManager _subObjPltt; + AscendingStackVramManager _subObjVram; + AscendingStackVramManager _textureVram; + AscendingStackVramManager _texturePaletteVram; + VBlankTextureLoader _vblankTextureLoader; + VramContext _mainVramContext; + VramContext _subVramContext; + Rgb6Palette _rgb6Palette; + Animator _fadeAnimator; + + TaskQueue<32, sizeof(TaskBase) + 32> _ioTaskQueue; + u32 _ioTaskThreadStack[2048 / 4]; + + std::unique_ptr _theme; + std::unique_ptr _topBackground; + std::unique_ptr _bottomBackground; + + IAppSettingsService& _appSettingsService; + volatile bool _exit = false; + + PadInputSource _keyInputSource; + TouchInputSource _touchInputSource; + SampledInputProvider _inputProvider; + InputRepeater _inputRepeater; + + FocusManager _focusManager; + + ChipView::VramToken _chipViewVram; + IconButton2DView::VramToken _iconButtonViewVram; + + bool _vcountIrqStarted = false; + + Point _lastTouchPoint = Point(0, 0); + + std::unique_ptr _settingsController; + SharedPtr _themeListTopView; + SharedPtr _themeListBottomView; + + void InitVramMapping() const; + void LoadTheme(); + void MainLoop(); + void Update(); + void HandleInput(); + void Draw(); + void VBlank(); + void VCountIrq(); +}; diff --git a/arm9/source/settings/ThemeInfoManager.cpp b/arm9/source/settings/ThemeInfoManager.cpp new file mode 100644 index 0000000..2516639 --- /dev/null +++ b/arm9/source/settings/ThemeInfoManager.cpp @@ -0,0 +1,81 @@ +#include "common.h" +#include +#include "core/mini-printf.h" +#include "fat/Directory.h" +#include "fat/File.h" +#include "ThemeInfoManager.h" + +ThemeInfoManager::ThemeInfoManager(const ThemeRepository& themeRepository) + : _themeRepository(themeRepository) + , _extraThemeInfo(std::make_unique[]>(themeRepository.GetThemeCount())) { } + +void ThemeInfoManager::LoadThemeInfo(int index) +{ + auto extraThemeInfo = SharedPtr::MakeShared(); + extraThemeInfo->themeInfo = _themeRepository.LoadThemeInfo(index); + if (extraThemeInfo->themeInfo) + { + LoadThemeIcon(extraThemeInfo); + LoadThemePreviewImage(extraThemeInfo); + _extraThemeInfo[index] = std::move(extraThemeInfo); + } +} + +void ThemeInfoManager::ReleaseThemeInfo(int index) +{ + _extraThemeInfo[index].Reset(); +} + +void ThemeInfoManager::LoadThemeIcon(SharedPtr& extraThemeInfo) +{ + char pathBuffer[256]; + mini_snprintf(pathBuffer, sizeof(pathBuffer), "/_pico/themes/%s", extraThemeInfo->themeInfo->GetFolderName()); + auto folderDir = std::make_unique(); + if (folderDir->Open(pathBuffer) == FR_OK) + { + FILINFO folderFileInfo; + while (folderDir->Read(&folderFileInfo) == FR_OK && folderFileInfo.fname[0] != 0) + { + if (!(folderFileInfo.fattrib & AM_DIR) && !strcasecmp(folderFileInfo.fname, "icon.bmp")) + { + extraThemeInfo->iconData = SharedPtr::MakeShared( + FastFileRef(folderDir->GetFatFsDirectory(), &folderFileInfo)); + break; + } + } + } +} + +void ThemeInfoManager::LoadThemePreviewImage(SharedPtr& extraThemeInfo) +{ + bool previewOk = false; + char pathBuffer[256]; + mini_snprintf(pathBuffer, sizeof(pathBuffer), "/_pico/themes/%s/preview.bin", extraThemeInfo->themeInfo->GetFolderName()); + auto file = std::make_unique(); + if (file->Open(pathBuffer, FA_READ) == FR_OK && + file->ReadExact(extraThemeInfo->previewImage, 256 * 192 * 2)) + { + previewOk = true; + } + file->Close(); + + if (!previewOk) + { + if (extraThemeInfo->themeInfo->GetType() == ThemeType::Custom) + { + mini_snprintf(pathBuffer, sizeof(pathBuffer), "/_pico/themes/%s/topbg.bin", extraThemeInfo->themeInfo->GetFolderName()); + if (file->Open(pathBuffer, FA_READ) == FR_OK && + file->ReadExact(extraThemeInfo->previewImage, 256 * 192 * 2)) + { + previewOk = true; + } + } + } + + if (!previewOk) + { + memset(extraThemeInfo->previewImage, 0, 256 * 192 * 2); + } + + DC_FlushRange(extraThemeInfo->previewImage, 256 * 192 * 2); +} diff --git a/arm9/source/settings/ThemeInfoManager.h b/arm9/source/settings/ThemeInfoManager.h new file mode 100644 index 0000000..60b71d7 --- /dev/null +++ b/arm9/source/settings/ThemeInfoManager.h @@ -0,0 +1,36 @@ +#pragma once +#include "common.h" +#include +#include "romBrowser/FileType/BmpFileIconData.h" +#include "themes/ThemeRepository.h" +#include "core/AtomicSharedPtr.h" + +class ThemeInfoManager +{ +public: + struct alignas(32) ExtraThemeInfo + { + u16 previewImage[256 * 192]; + std::unique_ptr themeInfo; + SharedPtr iconData; + }; + + ThemeInfoManager(const ThemeRepository& themeRepository); + + SharedPtr GetExtraThemeInfo(int index) const + { + return _extraThemeInfo[index].Lock(); + } + + void LoadThemeInfo(int index); + void ReleaseThemeInfo(int index); + + u32 GetItemCount() const { return _themeRepository.GetThemeCount(); } + +private: + const ThemeRepository& _themeRepository; + std::unique_ptr[]> _extraThemeInfo; + + void LoadThemeIcon(SharedPtr& extraThemeInfo); + void LoadThemePreviewImage(SharedPtr& extraThemeInfo); +}; \ No newline at end of file diff --git a/arm9/source/settings/viewModels/ThemeListItemViewModel.cpp b/arm9/source/settings/viewModels/ThemeListItemViewModel.cpp new file mode 100644 index 0000000..44ab19f --- /dev/null +++ b/arm9/source/settings/viewModels/ThemeListItemViewModel.cpp @@ -0,0 +1,11 @@ +#include "common.h" +#include "settings/ISettingsController.h" +#include "ThemeListItemViewModel.h" + +void ThemeListItemViewModel::Activate() +{ + if (_extraThemeInfo) + { + _settingsController->SelectTheme(_extraThemeInfo->themeInfo->GetFolderName()); + } +} diff --git a/arm9/source/settings/viewModels/ThemeListItemViewModel.h b/arm9/source/settings/viewModels/ThemeListItemViewModel.h new file mode 100644 index 0000000..f49308f --- /dev/null +++ b/arm9/source/settings/viewModels/ThemeListItemViewModel.h @@ -0,0 +1,58 @@ +#pragma once +#include "core/SharedPtr.h" +#include "romBrowser/viewModels/IRomBrowserItemViewModel.h" +#include "settings/ThemeInfoManager.h" +#include "themes/ThemeInfo.h" + +class ISettingsController; + +class ThemeListItemViewModel : public IRomBrowserItemViewModel +{ +public: + explicit ThemeListItemViewModel(ISettingsController* settingsController) + : _settingsController(settingsController) { } + + void Activate() override; + + void ShowGameInfo() override { } + + void SetIndex(int index) override + { + _index = index; + } + + void SetQueueTask(QueueTask queueTask) override + { + _queueTask = std::move(queueTask); + } + + void CancelQueueTask() override + { + _queueTask.CancelTask(); + } + + void DisposeQueueTaskWhenComplete() override + { + if (_queueTask.GetTask().IsCompleted()) + { + _queueTask.Dispose(); + } + } + + const ThemeInfoManager::ExtraThemeInfo* GetExtraThemeInfo() const + { + return _extraThemeInfo.GetPointer(); + } + + void SetExtraThemeInfo(SharedPtr extraThemeInfo) + { + _extraThemeInfo = std::move(extraThemeInfo); + } + +private: + int _index = -1; + QueueTask _queueTask; + SharedPtr _extraThemeInfo; + + ISettingsController* _settingsController; +}; diff --git a/arm9/source/settings/viewModels/ThemeListViewModel.cpp b/arm9/source/settings/viewModels/ThemeListViewModel.cpp new file mode 100644 index 0000000..02b6ed2 --- /dev/null +++ b/arm9/source/settings/viewModels/ThemeListViewModel.cpp @@ -0,0 +1,11 @@ +#include "common.h" +#include "settings/ISettingsController.h" +#include "ThemeListViewModel.h" + +ThemeListViewModel::ThemeListViewModel(ISettingsController* settingsController) + : _settingsController(settingsController) { } + +void ThemeListViewModel::NavigateUp() const +{ + _settingsController->NavigateUp(); +} diff --git a/arm9/source/settings/viewModels/ThemeListViewModel.h b/arm9/source/settings/viewModels/ThemeListViewModel.h new file mode 100644 index 0000000..6c51e2e --- /dev/null +++ b/arm9/source/settings/viewModels/ThemeListViewModel.h @@ -0,0 +1,23 @@ +#pragma once + +class ISettingsController; + +class ThemeListViewModel +{ +public: + explicit ThemeListViewModel(ISettingsController* settingsController); + + void NavigateUp() const; + + ISettingsController* GetSettingsController() const + { + return _settingsController; + } + + constexpr int GetSelectedItem() const { return _selectedItem; } + void SetSelectedItem(int selectedItem) { _selectedItem = selectedItem; } + +private: + ISettingsController* _settingsController; + int _selectedItem = -1; +}; diff --git a/arm9/source/settings/views/SettingsAppBarView.cpp b/arm9/source/settings/views/SettingsAppBarView.cpp new file mode 100644 index 0000000..8e710d6 --- /dev/null +++ b/arm9/source/settings/views/SettingsAppBarView.cpp @@ -0,0 +1,49 @@ +#include "common.h" +#include "backIcon.h" +#include "gui/GraphicsContext.h" +#include "gui/VramContext.h" +#include "gui/IVramManager.h" +#include "romBrowser/Theme/IRomBrowserViewFactory.h" +#include "SettingsAppBarView.h" + +SettingsAppBarView::SettingsAppBarView(SharedPtr viewModel, const IRomBrowserViewFactory* romBrowserViewFactory) + : _viewModel(std::move(viewModel)) +{ + _appBarView = romBrowserViewFactory->CreateAppBarView(0, 0, AppBarView::Orientation::Vertical, 1, 0); + AddChildTail(_appBarView.GetPointer()); + + _appBarView->SetButtonAction(APP_BAR_BUTTON_BACK, [] (IconButtonView* sender, void* arg) + { + ((ThemeListViewModel*)arg)->NavigateUp(); + }, _viewModel.GetPointer()); +} + +void SettingsAppBarView::InitVram(const VramContext& vramContext) +{ + ViewContainer::InitVram(vramContext); + + const auto objVramManager = vramContext.GetObjVramManager(); + if (objVramManager) + { + u32 backIconVramOffset = objVramManager->Alloc(backIconTilesLen); + dma_ntrCopy32(3, backIconTiles, objVramManager->GetVramAddress(backIconVramOffset), backIconTilesLen); + _appBarView->SetButtonIcon(APP_BAR_BUTTON_BACK, backIconVramOffset); + } +} + +SharedPtr SettingsAppBarView::MoveFocus(const SharedPtr& currentFocus, FocusMoveDirection direction, View* source) +{ + if (!currentFocus) + { + return nullptr; + } + if (source == _appBarView.GetPointer()) + { + return View::MoveFocus(currentFocus, direction, source); + } + else if (source == GetParent()) + { + return _appBarView->MoveFocus(currentFocus, direction, this); + } + return nullptr; +} diff --git a/arm9/source/settings/views/SettingsAppBarView.h b/arm9/source/settings/views/SettingsAppBarView.h new file mode 100644 index 0000000..42d1ead --- /dev/null +++ b/arm9/source/settings/views/SettingsAppBarView.h @@ -0,0 +1,38 @@ +#pragma once +#include "romBrowser/views/AppBarView.h" +#include "gui/views/ViewContainer.h" +#include "settings/viewModels/ThemeListViewModel.h" + +class RomBrowserDisplayMode; +class IRomBrowserViewFactory; + +class SettingsAppBarView : public ViewContainer +{ + SHARED_ONLY(SettingsAppBarView) + +public: + void InitVram(const VramContext& vramContext) override; + + Rectangle GetBounds() const override + { + return Rectangle(0, 0, 256, 192); + } + + SharedPtr MoveFocus(const SharedPtr& currentFocus, FocusMoveDirection direction, View* source) override; + + void Focus(FocusManager& focusManager) + { + _appBarView->Focus(focusManager, 0); + } + +private: + enum AppBarButton + { + APP_BAR_BUTTON_BACK = 0 + }; + + SharedPtr _viewModel; + SharedPtr _appBarView; + + SettingsAppBarView(SharedPtr viewModel, const IRomBrowserViewFactory* romBrowserViewFactory); +}; diff --git a/arm9/source/settings/views/ThemeAdapter.cpp b/arm9/source/settings/views/ThemeAdapter.cpp new file mode 100644 index 0000000..4c67650 --- /dev/null +++ b/arm9/source/settings/views/ThemeAdapter.cpp @@ -0,0 +1,91 @@ +#include "common.h" +#include "romBrowser/FileType/BmpFileIcon.h" +#include "romBrowser/Theme/IRomBrowserViewFactory.h" +#include "romBrowser/Theme/IThemeFileIconFactory.h" +#include "settings/SettingsController.h" +#include "settings/ThemeInfoManager.h" +#include "settings/viewModels/ThemeListItemViewModel.h" +#include "themes/ThemeInfo.h" +#include "ThemeAdapter.h" + +ThemeAdapter::ThemeAdapter(ISettingsController* settingsController, const IRomBrowserViewFactory* romBrowserViewFactory, + const IThemeFileIconFactory* themeFileIconFactory, VBlankTextureLoader* vblankTextureLoader) + : _settingsController(settingsController), _romBrowserViewFactory(romBrowserViewFactory) + , _themeFileIconFactory(themeFileIconFactory), _vblankTextureLoader(vblankTextureLoader) { } + +u32 ThemeAdapter::GetItemCount() const +{ + return _settingsController->GetThemeRepository().GetThemeCount(); +} + +void ThemeAdapter::GetViewSize(int& width, int& height) const +{ + width = 203; + height = 44; +} + +SharedPtr ThemeAdapter::CreateView() const +{ + return _romBrowserViewFactory->CreateBannerListItemView( + std::make_unique(_settingsController), _vblankTextureLoader); +} + +void ThemeAdapter::BindView(SharedPtr view, int index) const +{ + auto listItemView = static_cast(view.GetPointer()); + listItemView->SetGraphics(_listItemVramToken); + LOG_DEBUG("Binding %d\n", index); + auto queueTask = _settingsController->GetIoTaskQueue()->Enqueue([=, this] (const vu8& cancelRequested) + { + if (cancelRequested) + { + LOG_DEBUG("Task to load %d was canceled\n", index); + return TaskResult::Canceled(); + } + + LOG_DEBUG("Started task to load %d\n", index); + auto& themeInfoManager = _settingsController->GetThemeInfoManager(); + themeInfoManager.LoadThemeInfo(index); + if (cancelRequested) + { + return TaskResult::Canceled(); + } + + auto extraThemeInfo = themeInfoManager.GetExtraThemeInfo(index); + auto listItemView = static_cast(view.GetPointer()); + listItemView->GetViewModel().SetIndex(index); + if (extraThemeInfo) + { + listItemView->SetFirstLineAsync(nullptr, extraThemeInfo->themeInfo->GetName(), false); + listItemView->SetSecondLineAsync(nullptr, extraThemeInfo->themeInfo->GetAuthor()); + listItemView->SetThirdLineAsync(nullptr, extraThemeInfo->themeInfo->GetDescription()); + if (extraThemeInfo->iconData) + { + listItemView->SetIcon(std::make_unique(extraThemeInfo->iconData)); + } + else + { + listItemView->SetIcon(_themeFileIconFactory->CreateThemeFileIcon()); + } + listItemView->UploadIconGraphics(); + static_cast(listItemView->GetViewModel()).SetExtraThemeInfo(extraThemeInfo); + } + + return TaskResult::Completed(); + }); + + listItemView->GetViewModel().SetQueueTask(std::move(queueTask)); +} + +void ThemeAdapter::ReleaseView(SharedPtr view, int index) const +{ + auto listItemView = static_cast(view.GetPointer()); + listItemView->SetIcon(nullptr); + listItemView->GetViewModel().SetIndex(-1); + listItemView->GetViewModel().CancelQueueTask(); +} + +void ThemeAdapter::InitVram(const VramContext& vramContext) +{ + _listItemVramToken = _romBrowserViewFactory->UploadBannerListItemViewGraphics(vramContext); +} diff --git a/arm9/source/settings/views/ThemeAdapter.h b/arm9/source/settings/views/ThemeAdapter.h new file mode 100644 index 0000000..3be2b16 --- /dev/null +++ b/arm9/source/settings/views/ThemeAdapter.h @@ -0,0 +1,33 @@ +#pragma once +#include "gui/views/RecyclerAdapter.h" +#include "romBrowser/views/BannerListItemView.h" + +class IFontRepository; +class IRomBrowserViewFactory; +class ISettingsController; +class IThemeFileIconFactory; +class MaterialColorScheme; +class VBlankTextureLoader; +class VramContext; + +class ThemeAdapter : public RecyclerAdapter +{ +public: + ThemeAdapter(ISettingsController* settingsController, const IRomBrowserViewFactory* romBrowserViewFactory, + const IThemeFileIconFactory* themeFileIconFactory, VBlankTextureLoader* vblankTextureLoader); + + u32 GetItemCount() const override; + void GetViewSize(int& width, int& height) const override; + SharedPtr CreateView() const override; + void BindView(SharedPtr view, int index) const override; + void ReleaseView(SharedPtr view, int index) const override; + + void InitVram(const VramContext& vramContext); + +private: + ISettingsController* _settingsController; + const IRomBrowserViewFactory* _romBrowserViewFactory; + const IThemeFileIconFactory* _themeFileIconFactory; + VBlankTextureLoader* _vblankTextureLoader; + BannerListItemView::VramToken _listItemVramToken; +}; diff --git a/arm9/source/settings/views/ThemeListBottomView.cpp b/arm9/source/settings/views/ThemeListBottomView.cpp new file mode 100644 index 0000000..9c362dd --- /dev/null +++ b/arm9/source/settings/views/ThemeListBottomView.cpp @@ -0,0 +1,67 @@ +#include "common.h" +#include "gui/input/InputProvider.h" +#include "ThemeListBottomView.h" + +ThemeListBottomView::ThemeListBottomView(SharedPtr viewModel, const MaterialColorScheme* materialColorScheme, + const IRomBrowserViewFactory* romBrowserViewFactory, const IThemeFileIconFactory* themeFileIconFactory, + VBlankTextureLoader* vblankTextureLoader) + : _appBarView(SettingsAppBarView::CreateShared(viewModel, romBrowserViewFactory)) + , _recyclerView(RecyclerView::CreateShared(42, 0, 256 - 42, 192, RecyclerView::Mode::VerticalList)) + , _viewModel(std::move(viewModel)) +{ + AddChildTail(_appBarView.GetPointer()); + AddChildTail(_recyclerView.GetPointer()); + _recyclerView->SetPadding(0, 3); + _recyclerView->SetItemSpacing(0, 3); + _themeAdapter = SharedPtr::MakeShared( + _viewModel->GetSettingsController(), romBrowserViewFactory, themeFileIconFactory, vblankTextureLoader); +} + +void ThemeListBottomView::InitVram(const VramContext& vramContext) +{ + _appBarView->InitVram(vramContext); + _themeAdapter->InitVram(vramContext); // first initialize the shared vram for the items + _recyclerView->SetAdapter(_themeAdapter, 0); // set the adapter of the recycler + _recyclerView->InitVram(vramContext); // init the vram for the recycler and its items +} + +void ThemeListBottomView::Update() +{ + ViewContainer::Update(); + _viewModel->SetSelectedItem(_recyclerView->GetSelectedItem()); +} + +SharedPtr ThemeListBottomView::MoveFocus(const SharedPtr& currentFocus, FocusMoveDirection direction, View* source) +{ + if (!currentFocus) + { + return nullptr; + } + if (source == _appBarView.GetPointer()) + { + if (direction == FocusMoveDirection::Right) + { + return _recyclerView->MoveFocus(currentFocus, direction, this); + } + return nullptr; + } + else if (source == _recyclerView.GetPointer()) + { + if (direction == FocusMoveDirection::Left) + { + return _appBarView->MoveFocus(currentFocus, direction, this); + } + return nullptr; + } + return nullptr; +} + +bool ThemeListBottomView::HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) +{ + if (inputProvider.Triggered(InputKey::B)) + { + _viewModel->NavigateUp(); + return true; + } + return View::HandleInput(inputProvider, focusManager); +} diff --git a/arm9/source/settings/views/ThemeListBottomView.h b/arm9/source/settings/views/ThemeListBottomView.h new file mode 100644 index 0000000..6296e61 --- /dev/null +++ b/arm9/source/settings/views/ThemeListBottomView.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include "ThemeAdapter.h" +#include "gui/views/RecyclerView.h" +#include "gui/views/ViewContainer.h" +#include "settings/viewModels/ThemeListViewModel.h" +#include "settings/views/SettingsAppBarView.h" + +class IFontRepository; +class ISettingsController; +class MaterialColorScheme; + +class ThemeListBottomView : public ViewContainer +{ + SHARED_ONLY(ThemeListBottomView) + +public: + ThemeListBottomView(SharedPtr viewModel, const MaterialColorScheme* materialColorScheme, + const IRomBrowserViewFactory* romBrowserViewFactory, const IThemeFileIconFactory* themeFileIconFactory, + VBlankTextureLoader* vblankTextureLoader); + + void InitVram(const VramContext& vramContext) override; + void Update() override; + SharedPtr MoveFocus(const SharedPtr& currentFocus, FocusMoveDirection direction, View* source) override; + bool HandleInput(const InputProvider& inputProvider, FocusManager& focusManager) override; + + Rectangle GetBounds() const override + { + return Rectangle(_position, 256, 192); + } + + void Focus(FocusManager& focusManager) + { + _recyclerView->Focus(focusManager); + } + + SharedPtr _appBarView; +private: + SharedPtr _recyclerView; + SharedPtr _themeAdapter; + SharedPtr _viewModel; +}; diff --git a/arm9/source/settings/views/ThemeListTopView.cpp b/arm9/source/settings/views/ThemeListTopView.cpp new file mode 100644 index 0000000..80e9015 --- /dev/null +++ b/arm9/source/settings/views/ThemeListTopView.cpp @@ -0,0 +1,42 @@ +#include "common.h" +#include +#include +#include +#include "settings/SettingsController.h" +#include "themes/IFontRepository.h" +#include "themes/material/MaterialColorScheme.h" +#include "ThemeListTopView.h" + +ThemeListTopView::ThemeListTopView(SharedPtr viewModel, const MaterialColorScheme* materialColorScheme, + const IFontRepository* fontRepository) + : _viewModel(viewModel) + , _noPreviewLabel(Label2DView::CreateShared(64, 16, 25, fontRepository->GetFont(FontType::Medium11))) +{ + _noPreviewLabel->SetHorizontalAlignment(Alignment::Center); + _noPreviewLabel->SetText("No preview"); + _noPreviewLabel->SetPosition(128 - 32, 96 - 8); + _noPreviewLabel->SetBackgroundColor(materialColorScheme->inverseOnSurface); + _noPreviewLabel->SetForegroundColor(materialColorScheme->onSurfaceVariant); + AddChildTail(_noPreviewLabel.GetPointer()); +} + +void ThemeListTopView::VBlank() +{ + ViewContainer::VBlank(); + REG_DISPCNT_SUB = (REG_DISPCNT_SUB & ~0xF) | 5 | (4 << 8); + REG_BG2CNT_SUB = 0x4084; + REG_BG2HOFS_SUB = 0; + REG_BG2VOFS_SUB = 0; + gfx_setSubBg2Affine(256, 0, 0, 256, 0, 0); + + int selectedItem = _viewModel->GetSelectedItem(); + if (selectedItem != _lastSelectedItem) + { + auto extraThemeInfo = _viewModel->GetSettingsController()->GetThemeInfoManager().GetExtraThemeInfo(selectedItem); + if (extraThemeInfo) + { + dma_ntrCopy32(3, extraThemeInfo->previewImage, GFX_BG_SUB, 256 * 192 * 2); + _lastSelectedItem = selectedItem; + } + } +} diff --git a/arm9/source/settings/views/ThemeListTopView.h b/arm9/source/settings/views/ThemeListTopView.h new file mode 100644 index 0000000..56f0d05 --- /dev/null +++ b/arm9/source/settings/views/ThemeListTopView.h @@ -0,0 +1,29 @@ +#pragma once +#include "core/SharedPtr.h" +#include "gui/views/Label2DView.h" +#include "gui/views/ViewContainer.h" +#include "settings/viewModels/ThemeListViewModel.h" + +class IFontRepository; +class MaterialColorScheme; + +class ThemeListTopView : public ViewContainer +{ + SHARED_ONLY(ThemeListTopView) + +public: + ThemeListTopView(SharedPtr viewModel, const MaterialColorScheme* materialColorScheme, + const IFontRepository* fontRepository); + + void VBlank() override; + + Rectangle GetBounds() const override + { + return Rectangle(0, 0, 256, 192); + } + +private: + SharedPtr _viewModel; + int _lastSelectedItem = -1; + SharedPtr _noPreviewLabel; +}; diff --git a/arm9/source/themes/ThemeRepository.cpp b/arm9/source/themes/ThemeRepository.cpp new file mode 100644 index 0000000..699550f --- /dev/null +++ b/arm9/source/themes/ThemeRepository.cpp @@ -0,0 +1,27 @@ +#include "common.h" +#include "romBrowser/FileType/NullFileTypeProvider.h" +#include "romBrowser/SdFolderFactory.h" +#include "ThemeRepository.h" + +void ThemeRepository::Initialize() +{ + NullFileTypeProvider fileTypeProvider; + _themesFolder = SdFolderFactory(&fileTypeProvider).CreateFromPath("/_pico/themes"); + auto filterSortParams = SdFolderFilterSortParams(SdFolderSortType::Name, SdFolderSortDirection::Ascending, false); + _themeFolders = _themesFolder->FilterAndSort(filterSortParams, _numberOfThemes); +} + +u32 ThemeRepository::GetThemeCount() const +{ + return _numberOfThemes; +} + +std::unique_ptr ThemeRepository::LoadThemeInfo(u32 themeIndex) const +{ + if (themeIndex >= _numberOfThemes) + { + return nullptr; + } + + return _themeInfoFactory.CreateFromThemeFolder(_themeFolders[themeIndex]->GetFileName()); +} diff --git a/arm9/source/themes/ThemeRepository.h b/arm9/source/themes/ThemeRepository.h new file mode 100644 index 0000000..770939c --- /dev/null +++ b/arm9/source/themes/ThemeRepository.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include "romBrowser/SdFolder.h" +#include "themes/ThemeInfo.h" +#include "themes/ThemeInfoFactory.h" + +class ThemeRepository +{ +public: + void Initialize(); + + u32 GetThemeCount() const; + std::unique_ptr LoadThemeInfo(u32 themeIndex) const; + +private: + ThemeInfoFactory _themeInfoFactory; + std::unique_ptr _themesFolder; + u32 _numberOfThemes = 0; + std::unique_ptr _themeFolders; +}; diff --git a/arm9/source/themes/custom/CustomTheme.cpp b/arm9/source/themes/custom/CustomTheme.cpp index 3c9da38..7a0ead0 100644 --- a/arm9/source/themes/custom/CustomTheme.cpp +++ b/arm9/source/themes/custom/CustomTheme.cpp @@ -182,7 +182,8 @@ static CustomThemeInfo parseCustomThemeInfo(const JsonDocument& json) CustomTheme::CustomTheme(const TCHAR* folderName, const Rgb<8, 8, 8>& primaryColor, bool darkMode) : Theme(folderName, primaryColor, darkMode) , _customThemeInfo(sDefaultCustomThemeInfo) - , _romBrowserViewFactory(&_customThemeInfo, &_materialColorScheme, &_fontRepository) { } + , _romBrowserViewFactory(&_customThemeInfo, &_materialColorScheme, &_fontRepository) + , _themeFileIconFactory(&_materialColorScheme, &_fontRepository) { } void CustomTheme::LoadRomBrowserResources(const VramContext& mainVramContext, const VramContext& subVramContext) { diff --git a/arm9/source/themes/custom/CustomTheme.h b/arm9/source/themes/custom/CustomTheme.h index 3d7d0f2..c68bb7d 100644 --- a/arm9/source/themes/custom/CustomTheme.h +++ b/arm9/source/themes/custom/CustomTheme.h @@ -5,6 +5,7 @@ #include "CustomMainBackground.h" #include "CustomSubBackground.h" #include "romBrowser/Theme/custom/CustomRomBrowserViewFactory.h" +#include "romBrowser/Theme/Material/MaterialThemeFileIconFactory.h" #include "CustomTopBackgroundType.h" #include "../DefaultFontRepository.h" #include "CustomThemeInfo.h" @@ -22,7 +23,7 @@ public: const IThemeFileIconFactory* GetThemeFileIconFactory() const override { - return nullptr; + return &_themeFileIconFactory; } const IRomBrowserViewFactory* GetRomBrowserViewFactory() const override @@ -48,4 +49,5 @@ private: CustomRomBrowserViewFactory _romBrowserViewFactory; CustomTopBackgroundType _topBackgroundType; DefaultFontRepository _fontRepository; + MaterialThemeFileIconFactory _themeFileIconFactory; }; diff --git a/docs/Themes.md b/docs/Themes.md index 5dc972c..a93c783 100644 --- a/docs/Themes.md +++ b/docs/Themes.md @@ -84,19 +84,19 @@ Blend colors are used to fake translucency. They should be set to an approximati }, "topBannerTextLine0": { "position": { "x": 70, "y": 126 }, - "width": 176, + "width": 168, "textColor": { "r": 30, "g": 30, "b": 30 }, "blendColor": { "r": 200, "g": 200, "b": 200 } }, "topBannerTextLine1": { "position": { "x": 70, "y": 141 }, - "width": 176, + "width": 168, "textColor": { "r": 30, "g": 30, "b": 30 }, "blendColor": { "r": 200, "g": 200, "b": 200 } }, "topBannerTextLine2": { "position": { "x": 70, "y": 155 }, - "width": 176, + "width": 168, "textColor": { "r": 30, "g": 30, "b": 30 }, "blendColor": { "r": 200, "g": 200, "b": 200 } }, @@ -129,3 +129,9 @@ Blend colors are used to fake translucency. They should be set to an approximati ## Background music All themes support background music by placing DSP-ADPCM encoded `.bcstm` files in a `bgm` folder inside the theme folder. Looping is supported. When multiple `.bcstm` files are provided, the background music will be selected at random each time Pico Launcher is started. + +## Theme selector icon +A theme can have an `icon.bmp` file that is shown in the theme list when selecting a theme. It must be **32×32 pixels, 4 bpp (16 colors), uncompressed `.bmp`** file, with the first palette color treated as transparent. + +## Theme selector preview image +A theme can have a `preview.bin` file that is shown on the top screen in the theme selection screen. It must be a 256x192 pixels 15 bpp bitmap (same format as `topbg.bin` and `bottombg.bin`). When it is not provided, `topbg.bin` is displayed instead. If that does not exist either, nothing is shown on the top screen. diff --git a/libs/libtwl b/libs/libtwl index 55ffbc9..aa3b2a2 160000 --- a/libs/libtwl +++ b/libs/libtwl @@ -1 +1 @@ -Subproject commit 55ffbc9e45b27d44cfee4404caac5fda19d4b8cc +Subproject commit aa3b2a23c10185a10449ffa685bb7933d5d5a784