From 8f0e2246f90b8dca7672b7b5e19fb143aad4f157 Mon Sep 17 00:00:00 2001 From: Jonathan Payne Date: Sat, 16 Aug 2014 20:55:57 -0700 Subject: [PATCH] Add a real High Scores screen. (cherry picked from commit 4c5bfa5e0eb351a0d90c70413a7cd8622007d188) --- .../Fonts/ScreenHighScores Name.redir | 1 + .../Fonts/ScreenHighScores Score.redir | 1 + .../Fonts/ScreenHighScores Text.redir | 1 + .../ScreenHighScores ScrollerItem/default.lua | 100 +++++++++++++++++ .../empty (doubleres).png | Bin 0 -> 628 bytes .../filled (doubleres).png | Bin 0 -> 721 bytes .../frame (doubleres).png | Bin 0 -> 3674 bytes Themes/_fallback/Languages/en.ini | 37 ++++++- Themes/_fallback/Scripts/02 Branches.lua | 2 +- Themes/_fallback/metrics.ini | 36 ++++++ .../_difficulty frame.png | Bin 0 -> 878 bytes .../ScreenHighScores decorations/default.lua | 40 +++++++ .../ScreenDemonstration StageDisplay.redir | 1 + .../Graphics/ScreenGameplay StageDisplay.lua | 12 +- .../ScreenHighScores ScrollerItem/default.lua | 104 ++++++++++++++++++ .../empty (doubleres).png | Bin 0 -> 628 bytes .../filled (doubleres).png | Bin 0 -> 721 bytes .../frame (doubleres).png | Bin 0 -> 3674 bytes .../ScreenSelectMusic CourseContentsList.lua | 37 +------ Themes/default/Scripts/02 TextBanner.lua | 37 +++++++ Themes/default/metrics.ini | 19 ++++ 21 files changed, 392 insertions(+), 36 deletions(-) create mode 100644 Themes/_fallback/Fonts/ScreenHighScores Name.redir create mode 100644 Themes/_fallback/Fonts/ScreenHighScores Score.redir create mode 100644 Themes/_fallback/Fonts/ScreenHighScores Text.redir create mode 100644 Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/default.lua create mode 100644 Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/empty (doubleres).png create mode 100644 Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/filled (doubleres).png create mode 100644 Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/frame (doubleres).png create mode 100644 Themes/default/BGAnimations/ScreenHighScores decorations/_difficulty frame.png create mode 100644 Themes/default/BGAnimations/ScreenHighScores decorations/default.lua create mode 100644 Themes/default/Graphics/ScreenDemonstration StageDisplay.redir create mode 100644 Themes/default/Graphics/ScreenHighScores ScrollerItem/default.lua create mode 100644 Themes/default/Graphics/ScreenHighScores ScrollerItem/empty (doubleres).png create mode 100644 Themes/default/Graphics/ScreenHighScores ScrollerItem/filled (doubleres).png create mode 100644 Themes/default/Graphics/ScreenHighScores ScrollerItem/frame (doubleres).png diff --git a/Themes/_fallback/Fonts/ScreenHighScores Name.redir b/Themes/_fallback/Fonts/ScreenHighScores Name.redir new file mode 100644 index 0000000000..9533167834 --- /dev/null +++ b/Themes/_fallback/Fonts/ScreenHighScores Name.redir @@ -0,0 +1 @@ +Common Bold \ No newline at end of file diff --git a/Themes/_fallback/Fonts/ScreenHighScores Score.redir b/Themes/_fallback/Fonts/ScreenHighScores Score.redir new file mode 100644 index 0000000000..5c6053f7f1 --- /dev/null +++ b/Themes/_fallback/Fonts/ScreenHighScores Score.redir @@ -0,0 +1 @@ +Common Normal \ No newline at end of file diff --git a/Themes/_fallback/Fonts/ScreenHighScores Text.redir b/Themes/_fallback/Fonts/ScreenHighScores Text.redir new file mode 100644 index 0000000000..5c6053f7f1 --- /dev/null +++ b/Themes/_fallback/Fonts/ScreenHighScores Text.redir @@ -0,0 +1 @@ +Common Normal \ No newline at end of file diff --git a/Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/default.lua b/Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/default.lua new file mode 100644 index 0000000000..212634d368 --- /dev/null +++ b/Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/default.lua @@ -0,0 +1,100 @@ +local t = Def.ActorFrame { + InitCommand=cmd(runcommandsonleaves,cmd(ztest,true)); +}; + +t[#t+1] = LoadActor("frame") .. { + InitCommand=cmd(diffusealpha,0.1;); +}; + + +t[#t+1] = Def.TextBanner { + InitCommand=cmd(x,-196;y,0;Load,"TextBannerHighScores"); + SetCommand=function(self, params) + if params.Song then + self:SetFromSong( params.Song ); + self:diffuse( SONGMAN:GetSongColor(params.Song) ); + else + self:SetFromString( params.Course:GetTitle() ); + self:diffuse( SONGMAN:GetCourseColor(params.Course) ); + end + end; +}; + +local NumColumns = THEME:GetMetric(Var "LoadingScreen", "NumColumns"); + +local c; +local Scores = Def.ActorFrame { + InitCommand = function(self) + c = self:GetChildren(); + end; +}; +t[#t+1] = Scores; + +for idx=1,NumColumns do + local x_pos = -60 + 80 * (idx-1); + Scores[#Scores+1] = LoadFont(Var "LoadingScreen","Name") .. { + Name = idx .. "Name"; + InitCommand=cmd(x,x_pos;y,6;shadowlengthx,0;shadowlengthy,2;shadowcolor,color("#000000");maxwidth,68;); + }; + Scores[#Scores+1] = LoadFont(Var "LoadingScreen","Score") .. { + Name = idx .. "Score"; + InitCommand=cmd(x,x_pos;y,-10;shadowlengthx,0;shadowlengthy,2;shadowcolor,color("#000000");maxwidth,68;); + }; + Scores[#Scores+1] = LoadActor("filled") .. { + Name = idx .. "Filled"; + InitCommand=cmd(x,x_pos;); + }; + Scores[#Scores+1] = LoadActor("empty") .. { + Name = idx .. "Empty"; + InitCommand=cmd(x,x_pos;); + }; + +end + +local sNoScoreName = THEME:GetMetric("Common", "NoScoreName"); + +Scores.SetCommand=function(self, params) + local pProfile = PROFILEMAN:GetMachineProfile(); + + for name, child in pairs(c) do + child:visible(false); + end + for idx=1,NumColumns do + c[idx .. "Empty"]:visible(true); + end + + local Current = params.Song or params.Course; + if Current then + for idx, CurrentItem in pairs(params.Entries) do + if CurrentItem then + local hsl = pProfile:GetHighScoreList(Current, CurrentItem); + local hs = hsl and hsl:GetHighScores(); + --[[Warn( tostring(CurrentItem:GetStepsType()) .. ", " .. + tostring(CurrentItem:GetDifficulty()) .. ": " .. + tostring(hsl) .. ", " .. + tostring(#hs) );]] + local name = c[idx .. "Name"]; + local score = c[idx .. "Score"]; + local filled = c[idx .. "Filled"]; + local empty = c[idx .. "Empty"]; + + --assert( c[sNameType], sNameType ); + --assert( c[sScoreType], sScoreType ); + + name:visible( true ); + score:visible( true ); + filled:visible( true ); + empty:visible( false ); + if hs and #hs > 0 then + name:settext( hs[1]:GetName() ); + score:settext( FormatPercentScore( hs[1]:GetPercentDP() ) ); + else + name:settext( sNoScoreName ); + score:settext( FormatPercentScore( 0 ) ); + end + end + end; + end +end; + +return t; diff --git a/Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/empty (doubleres).png b/Themes/_fallback/Graphics/ScreenHighScores ScrollerItem/empty (doubleres).png new file mode 100644 index 0000000000000000000000000000000000000000..51816916cbe5e2a02994318c840229e21299042e GIT binary patch literal 628 zcmV-)0*n2LP)pY<5TpP9@94z?dXT74NDETXnPfIu*LK}vx6V%ThC^9+Iy*C+ z&I;j~)k;`@Mrwf?peCqJ*AJi#XiJ|f&>HkvH88@BKz&eHaBT`&faajsH86Vb8q_Um zha=Dol#~sO-@78O)=Cab438JklTD}u7C(qveghgffYtM0NpXKPFvjW~s9iw;XpmD@ z6z7G3I|Lh6ShbMnlAw1*fbni`Eknjdi1ewF?DdQFoCVX0J)4y`)2y7y^56t?!Qi2G zLJo~g9&S_V;$kB`;dS7#qtf-4cpm2gN&lv;Hvl{rAX)G^=GBnhmbXN1N z3JqDFO|SVoYBD;ELgCf)){Hh2N6c*-9G3=T=yZyC`x7eaLisz1ScVzHr)0Y?h zb9{512oDZrbi<(rj*r+Mdu6T1!<2LK{;BwR9uiYBC8C6bMepoOfB^uQYh;T=5=IOF O0000ra@ocD)4hB}-f* zN`mv#O3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrIztFeQ7sIEGZ*dNViMo5@k6?YQrz zEweA~_2~HbUtWuAS3pESsCw&o{@TT-IBaT2mY%HE!X_{D?9PjB^-rU?qHOSy)2OY~huMbkyxx4AiwU56Rp_l%~zjSzruXq38tOPy%;!{VX(mf0g;3`m=VGa22&UW*dVY= z;mic126boAGzZxOlN-4%FXemSDW0gnFDv@28E9p$=(4A3bM~t_iq1UWU#P&XKx$}XZNft>_R4w7yEyT zyJX92pdxkm_YY~uQ%|2qU0N8{x;$C0<#J2lmwT65m$;wh@;)!~qjdg8kv8GqF}7PC zohh6bbg^Q3%+8O$=A2eO^P7rjO=qt{@DK}0ta5hM~VWb}H75H%wtVHlklQ8T)zLDW&A z2SJV!678CE|AqVUe%SkY*0b09d)HoTe^@L2wwXQ+tUAduU)J$?Lr9((%u@)$xOJid>7JnlVk2Ow|; zWrcuRZLq2x%^zqR$05^=eJokXc`UUPk<6)rqP!IJMsd6a(<~Nk47$1`oW1#R#L3CX zBo+%X>IBLuvK8L9$&v5k68cUSL*98!G#{-Ep4UyPub1tkYKO^iJn{k zhHsHQo!yHo5}M(Z{Jwymyw;8P@fjZxI1W=)y?Fyi)(VIM$Ee5w&NLS%bv^ciZc{t^ z4iPen2z?q z&e4=;56b3{374b$wtrcN{8X09+wPwQ4$)Q&4JjmJX&uEkKapPCaB*2aUmY&>)dXPC zKWyY&OtSVGQiT-heg0Nphs5(PRsNHsM2{Le%{q|3F=MmuOUR9G!Hb6J>D85$DWgtp zd*?oz&~rq)BhKdR!S68D)1$+0txNpjG7jPTB*)*{2M$aMuMfYZh;o@-OVK~Ar@A=h z8oSYH=+XceWnQ*m^h?&sN!phwyb-VcQlv{@^uldvLF|NBeL)^n-B%|HNfj@4a3%g_ zEJP3Y$1NQJu-D|%_Engi80i_gI2>@Xt8u2EF947phA;g9xU0i20qv{R=phF{CqG=Y zN{jQLja>{!dcE!HY#Y_7lR}g>e`mWky*8yA^7S1RubNzPI1A61 zG+$bYcGyQ+HD9_v&g6M*!p-3nBwD@XOwPPBaYQZ&aK2=6w(RI*-Zldg#zcOe&vDEa zH;hx|4Wum-pgb@Gu06F!SCnG!=ryLQ^a7cP)0k#`>Gbd#3$?G*b&!T)#cNS|Z>hex z`Ag@du;%A}dGz6$T9QJ+`j=8qx|tMpNRJfmJ3E5jVvjx(-(dkT8bp;wThI0!{>&z=(HqUrbk*lJ1GvhThT$144*+$yPi zmW&qcU5@2kaRHP;KE+PEyZ~!iX%Sn@B=;moX)u!2(73St?W?hCo@|~+_bR{pH!{q< z;x^0tVl&#mq5nPeJMlpPHBAglWKSGIm?M{+j2*!dz+RbUQp7Qq$k79pQk34xTF<7- z_JP4gv7*mdQu`=h8NCvG#VINYEx{CF<}p;TeONyD8 zWyNWQC{Zbn#UP4(pc?PPY|r9JZ97al%pvbB@~a(}o4a|aTsdk3#dy7FN@Jdc%XbP^ z4^BUOD%zBF#?_RlhAAmfg2)=l+SFR^r+a9SEob>1zxFqySQkcT?uRAJGw+HliEtLl znKVed-|@m^WM;ri4N5Ia^|x9SDz?$6q88mI+mmowtsWzxJ3{)1l%cDrb*pKsIW#4j z)l^OSutEakRmfS;q!aMzA$lh(uk|i6&%_5kAJnq`=X$8*8T8Ei5BgA_8cteE%}7h=+J}|I=^zxT#QO>7*TyUuJ^YdUDCboJInmb-re5a?*vH& zc?FG4H%)hPEKM7VM2b{QR7`pX2L|5`PGrmHs!31Etmm%hPUbGuJJ|)=iD8SeAKeXW zR_uywcd*S5qwSPz3*j(3hg!XIRJp)JQ+X4b0o`DhW>%Uvf#|6E2m2XYQqNJfIz@`F zznOS$a0!XAHk#H?(sJfAc4dPgI)>mXx8 z5&<8kAD)t3#xnJbblyW*<&Nni*bohmBlqJH?7=Sr)-ept&rT*y6vih>B;=Ihft>b_quD-Xv-@L;o&oO!d@|^F&?IQSM z1fY=uL_; zHIzDZk2d;t*!PJqWX@~Oi5+3oLea6&HZdB>zH#ttBhs1j0VA`J#|t`tbTV}2a}m2ewgcmE6x{HE@pUB$(F%o!4_X&axA$Y0P)k(HA#7Qa zy$-%X1w-uz(P-8Z2}UvH3{8_bvs>vuwdh5QS(60zm;wZnDTCU%+7UM-M-)clrXY7j zxy|+rL`{QV{zz?>5905VEfiaAh!QG!(QHCvGMB5I$C~q$$6H2CxkWniW$Ft*Z49qz z8WypMSo3(=U*;ZNbKdnZv0jq<71?L6+81S4ZN(|E+C|@?cEXdQWHktP8;?(e@qJ1e zrFl08w+Cwb@Glf!@4mU%W^89%e2FcLF}4xsg0Hod-B+qn^$WsNF0)*{8DmXarus1f zE9yONUb=0QSrOJE7;Nelez&bJqOFd|Yl{j-xf&h1H9NWOU=EkGU8r;Z6NBPZXNga! zV8*j$vOJ#>o(){(jP>dJls%jNp`^64!EM-M)MI09UOdm9HUpEnmPz}NW_soW&4TrZ z?ZaQXc*)E`VSH007SizUlj_H2cl76>K@|Cs~Gxg7{co-4PblhXy{lxI3_DG{59AtoDV+L$Nxq5T29qA$Y>w>`QFS%#8?_)Z#W6{3KbeA z@q5+@{}vmv?mDz^pU!8uk=}oCRQDorU8PxN=+53p|GgUgDwEAeo198zNAFGlP1WbXyD9`x$1;;1bfV4NSO0YJT4-dJc0)vr&UE>Vr`PGpk=Vg5Ga-* z5_Me@gUk};p&(z1;30`}VxYfb9r;bp?uUe}8`IT*`OU^0=hojvL4CPzvSAnAm46Bv zp$=4+5drlb!$ZWAPk#>IQ#3*`zPpNztf)`JWt*Q!%=l?1b4KP z!(7??<=66g!G6mHQ&aGahvh5GtT!~PokDvZm zjD{UzBmYt$=*V(=*e;=`2e|Yu5(1hq68e3>E?__iO3LWPl}m6+=OO$FC#*#n43HKP z%$ES(k%$mLkK%Gl03hlAAO3HWlX2gbFl>P$v2hI#0&(iyD*S_|B~a?$UM1XkLS>M= zDVdw$Tm+GQuOBm0a@V@)7r}B$ybD`TId|X9QzMvDH6i03PmVp%!FCSVf8VP8&*nxu z?~IN})5Fj@EDga4{a{WjWCkkUqdryHYM4$a`L}~I6;HDheX@QsHg1?BcPl}}t>3Da zFF#+WTClD!O&n)AAw=?%A`d2sd4qXl-uROnfQt)aklLk0QEB5Ga(N02b 3 and hour < 6 and "ScreenNoise" or "ScreenInit" + return hour > 3 and hour < 6 and "ScreenNoise" or "ScreenHighScores" end, TitleMenu = function() -- home mode is the most assumed use of sm-ssc. diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index f511122447..e94fb0c093 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -39,6 +39,9 @@ CourseDifficultiesToShow="easy,medium,hard" # be shown in lights mode! So don't hide it here. StepsTypesToHide="" +# Score placeholder for ScreenHighScores +NoScoreName="STEP" + # The number of entries before "Various" is shown on the BPMDisplay, etc. MaxCourseEntriesBeforeShowVarious=10 @@ -1497,6 +1500,11 @@ ArtistOnCommand=visible,false ArtistPrependString="/" AfterSetCommand=%TextBannerAfterSet +[TextBannerHighScores] +Fallback="TextBanner" +AfterSetCommand=%TextBannerHighScoreAfterSet + + [WheelNotifyIcon] ShowTraining=false BlinkPlayersBest=true @@ -4503,6 +4511,34 @@ AllowStyleTypes="TwoPlayersTwoSides" MinSecondsToStep=0 MinSecondsToMusic=0 +[ScreenHighScores] +Fallback="ScreenAttract" +Class="ScreenHighScores" +NextScreen="ScreenInit" +PrevScreen="ScreenDemonstration" +StartScreen=Branch.TitleMenu() + +TimerSeconds=-1 + +HighScoresType="HighScoresType_AllSteps" +MaxItemsToShow=50 +NumColumns=5 +ColumnDifficulty1="Difficulty_Beginner" +ColumnDifficulty2="Difficulty_Easy" +ColumnDifficulty3="Difficulty_Medium" +ColumnDifficulty4="Difficulty_Hard" +ColumnDifficulty5="Difficulty_Challenge" +ColumnStepsType1=GAMEMAN:GetFirstStepsTypeForGame(GAMESTATE:GetCurrentGame()) +ColumnStepsType2=GAMEMAN:GetFirstStepsTypeForGame(GAMESTATE:GetCurrentGame()) +ColumnStepsType3=GAMEMAN:GetFirstStepsTypeForGame(GAMESTATE:GetCurrentGame()) +ColumnStepsType4=GAMEMAN:GetFirstStepsTypeForGame(GAMESTATE:GetCurrentGame()) +ColumnStepsType5=GAMEMAN:GetFirstStepsTypeForGame(GAMESTATE:GetCurrentGame()) +ScrollerItemsToDraw=7 +ScrollerSecondsPerItem=0.4 +ManualScrolling=false +ScrollerOnCommand=x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y+36;SetMask,608,40 +ScrollerItemTransformFunction=function(self,offset,itemIndex,numItems) self:y(46.1*offset) end + [ScreenNoise] Fallback="ScreenAttract" Class="ScreenAttract" diff --git a/Themes/default/BGAnimations/ScreenHighScores decorations/_difficulty frame.png b/Themes/default/BGAnimations/ScreenHighScores decorations/_difficulty frame.png new file mode 100644 index 0000000000000000000000000000000000000000..0e04d83a89b0a97088b05bb7189a81907077fa0e GIT binary patch literal 878 zcmeAS@N?(olHy`uVBq!ia0vp^OMqB~gBeH~+)iB0z`$q};1lBd|NnoW2oUJ%>ekfM zw6wICnwq-1yHA`r(ZIl9=FFK+PEOt3-6bU@VPRo@etsGn8rj*|si~=PadDQGmUeb_ z^XJcBx^$_EiptTWM^~?2?d$9N@83T~MMa3Q#E|>;?K3nq1gc!ScJ0E23%`E-s;sPh z^X5%$ZSBK{4+F*Dzkd%TpFVxMY15{M4C&rL zuP$7;aPHhWpsqJ>-kdshDkUXl@7}#YmB)@9d-v`gkW^4mICA8Ot*!07d-wG9^?@pv zFJJEH=y>wvNucf9w{Hg;?&9L&=H_#=Ev^YcAF zDf{%%@1viO-{k$J`R)1F6W=R-pZnDP@!N;@Z-2hO`c&)P&$mb4p8j&;&Dp+p&tG;< zIQ!zqnV+}rJf6h+mD>*(U#*@ljv*CsZ_ashH91HyJoxvKX>-?sIg-cITPHorR#fiL z78iQtrcrhA?|Olri=0t^y7vj!tiJy<*+-=Csc^|3Ej^ZGZ=-@GOjD+mG^uLtxc%&| z*h0PhSiO=@3g-{sna%O_^M_k+ODEm#e=On4W)*C*Zob*|lLG6+XGN)(teJA}oxrOl z?4ElaSNR>d?8)ToHu02{!u*uX1)+75^V6PRU}F$qV*&;*OJk$ws#(jJ!tehrKlqoY zUO2`ls&PqqRNoT0sIDckQEe%DQJqV8qMDxE-Xb??{!L2@MhTWh8Z%g!EoU@DObd}v^K$1wffjAuX8P?Q@@Cxo*KiLt+_LQ&DtfdI>ALY5s&ka zzbn*WS*Xy{wUqlphGNsc_CG37(HEV$Rc1u&{BL?ArYxb5`#jgOx%_VbJTfkD708Dr zy%Sscw@KM;rmfWyKJMvZCsRI|DQrodyhLl})1GziCys7TnHCsuj>D@b*l^mH<>~!~ ie}6_g|EfOzoUx?Wb90{>vnntNFnGH9xvX 0 then + name:settext( hs[1]:GetName() ); + score:settext( FormatPercentScore( hs[1]:GetPercentDP() ) ); + else + name:settext( sNoScoreName ); + score:settext( FormatPercentScore( 0 ) ); + end + end + end; + end +end; + +return t; diff --git a/Themes/default/Graphics/ScreenHighScores ScrollerItem/empty (doubleres).png b/Themes/default/Graphics/ScreenHighScores ScrollerItem/empty (doubleres).png new file mode 100644 index 0000000000000000000000000000000000000000..51816916cbe5e2a02994318c840229e21299042e GIT binary patch literal 628 zcmV-)0*n2LP)pY<5TpP9@94z?dXT74NDETXnPfIu*LK}vx6V%ThC^9+Iy*C+ z&I;j~)k;`@Mrwf?peCqJ*AJi#XiJ|f&>HkvH88@BKz&eHaBT`&faajsH86Vb8q_Um zha=Dol#~sO-@78O)=Cab438JklTD}u7C(qveghgffYtM0NpXKPFvjW~s9iw;XpmD@ z6z7G3I|Lh6ShbMnlAw1*fbni`Eknjdi1ewF?DdQFoCVX0J)4y`)2y7y^56t?!Qi2G zLJo~g9&S_V;$kB`;dS7#qtf-4cpm2gN&lv;Hvl{rAX)G^=GBnhmbXN1N z3JqDFO|SVoYBD;ELgCf)){Hh2N6c*-9G3=T=yZyC`x7eaLisz1ScVzHr)0Y?h zb9{512oDZrbi<(rj*r+Mdu6T1!<2LK{;BwR9uiYBC8C6bMepoOfB^uQYh;T=5=IOF O0000ra@ocD)4hB}-f* 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