diff --git a/Meta/A_Little_Story.json b/Meta/A_Little_Story.json new file mode 100644 index 0000000..ae34a7a --- /dev/null +++ b/Meta/A_Little_Story.json @@ -0,0 +1,12 @@ +{ + "SongName":"A Little Story", + "Lyricist":"", + "Composer":"Valentin", + "Adapter":"Kouchya", + "Comment":"", + "Abstract":"一直超想做的一首曲子>ω<\n终于做出来啦>ω<", + "Origin":"", + "Image":"", + "Uploader":"Kouchya", + "Tags":[] +} \ No newline at end of file diff --git a/Meta/For_Elise.json b/Meta/For_Elise.json new file mode 100644 index 0000000..50ae94f --- /dev/null +++ b/Meta/For_Elise.json @@ -0,0 +1,12 @@ +{ + "SongName":"致爱丽丝", + "Lyricist":"", + "Composer":"", + "Adapter":"", + "Comment":"", + "Abstract":"", + "Origin":"", + "Image":"", + "Uploader":"", + "Tags":[] +} \ No newline at end of file diff --git a/Songs/A_Little_Story.tm b/Songs/A_Little_Story.tm new file mode 100644 index 0000000..9904b12 --- /dev/null +++ b/Songs/A_Little_Story.tm @@ -0,0 +1,332 @@ +// A Little Story +// Valentin 曲 +// Kouchya 改编 + +#include Benzene + +(4/4)(105)(1=C) + +//-------------------- Section A -------------------- + +<:t:>1_5_1'_5_ + +Oct(1) +&05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_^|%%_2'.4#_5_^|%.%_5'_.4'#_.2'_| +05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_|5T_.5_.5q_.7_.6_5_|[256]-4#-*|| + +Oct(-1) +Rest(16)| +3--4#_5_^|%-4#-|3--4#_5_|6---|| + + +&{3*@t?:{3-1-|5,-}|4,#_2_5_2_}|(Oct:-1)@t?:{3-1-}|2po---*|| + +//-------------------- Section B -------------------- + +<:t:>1_5_1'_5_ + +<:w:>1_5_1_5,_7,_5_1_5,_ + +<:b:>1.%_ + +Dur(1)Seg(1/4) +&054#25.4#.2^|Dur(0)%---|Dur(1)054#25.4#.^%|5p----5o4#o2o^| +%75-2.5.4#|5---1'.7.5^|%2q4#25.4#.2|Dur(0)(5^)6---*|| + +Oct(-1)(70%) +3--4#_5_^|%-4#-|3--4#_5_^|%-4#-| +3--5|6-4#.5_|3--5_3_|6-4#-|| + +(84%)Oct(-1) +&{2*@t?:{3-1-}|@w?:{5---}}| +@t?:{3-1-}|5(1=)2'-4#_2'_5_2'_|@t?:{3-1-|2-}2(1=)6,-*|| + +(90%)Oct(-3) +@b?:{3-1-|5-4#-|3-1-|5-}52| +@b?:{3-1-|5-4#-|3-1-}|2---|| + + +{8*bcbc}|| + +(85%) +{8*3,,_0.%_0.}|| + +Dur(1) +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section C -------------------- + +<:t:>1_5_1'_5_ + +<:v:>1_6b_2b_6b_ + +<:b:>1.%_ + +Dur(1)Seg(1/4) +&054#25.4#.2^|Dur(0)%.2'1'7_^|Dur(1)%54#25.4#.2^|Dur(0)%-2'.5'_^| +%_4'#2'_^%-^|%.5'4'#2'_^|%-1'.7_^|%---*|| + +Oct(-1)(70%) +5--3|2-2'1'|7--5|6-4#-| +3t---|2'-1'-|7-1'.7_^|%:---^|| + +(84%)Oct(-1) +&{3*@t?:{3-1-|5-}@v?:{4#-}}|3m-2M.1M_^|%---*|| + +(90%)Oct(-3) +@b?:{3-1-|5-4#-|3-1-|5-}52| +@b?:{3-1-|5-4#-|3-1-}|2---|| + + +{4*b-b-|b_d=d=d=b=b_b-}|| + +(58%)Stac(1/2, 0) +{4*0---|0_5'=%=%=0_.0-}|| + + +{8*0x0x}|| + +(85%) +{8*3,,_0.%_0.}|| + +Dur(1) +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section D -------------------- + +<:t:>1_5_1'_5_ + +<:s:>1=0= + +Oct(1) +&05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_^|%%_2'.4#_5_^|%.5'(2=)5.5'_6'_| +{3*5'_.5_.5'_^5'(2=)5.6'_}|4#%'_%,_%'%_%,_*|| + +Oct(-1) +7--@s?:{6|7---}|7--@s?:{6|7---}| +7-@s?:{67}|7-@s?:{67}|(60%)5T-(55%)5q-|(50%)2M---|| + +Stac(1/2,0) +&{3*(1-)3m-(1-)1M-|(1-)5,Mi-(1-)[6,12]-}|(Oct:-1)(1-)3m-(1-)1M-|2M---*|| + +(90%)Oct(-3) +Rest(16)| +3-1-|5-4#-|3-1-|2---|| + + +{4*b-b-|b_d=d=d=b=b_b-}|| + +(58%)Stac(1/2, 0) +{4*0---|0_5'=%=%=0_.0-}|| + + +{8*0x0x}|| + +(85%) +{8*3,,0%0}|| + +Dur(1) +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section E -------------------- + +<:t:>1_5_1'_5_ + +Oct(1) +&05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_^|%%_2'.4#_5_^|%.%_5'_.4'#_.2'_| +05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_|5T_.5_.5q_.7_.6_5_|[256]-4#-*|| + +Oct(-1) +0(55%)3.0_(70%)3_4#_|5_^(55%)%.4#-|6=0_.3.0_(70%)3_4#_|5_^(55%)%.4#-| +03.0_(70%)3_4#_|5_^(55%)%.(70%)2'_`1'_`7_`6_`|7_^(55%)%.5-|(70%)6:--0|| + + +&{3*@t?:{3-1-|5,-}|4,#_2_5_2_}|(Oct:-1)@t?:{3-1-}|2po---*|| + + +{4*b-b-|b_d=d=d=b=b_b-}|| + +(58%)Stac(1/2, 0) +{4*0---|0_5'=%=%=0_.0-}|| + + +{8*0x0x}|| + +(80%) +{8*3,,0%0}|| + +(90%)Dur(1) +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section F -------------------- + +<:t:>1_5_1'_5_ + +<:w:>1_5_1_5,_7,_5_1_5,_ + +<:b:>1.%_ + +Dur(1)Seg(1/4) +&054#25.4#.2^|Dur(0)%---|Dur(1)054#25.4#.^%|5p----5o4#o2o^| +%75-2.5.4#|5---1'.7.5^|%2q4#25.4#.2|Dur(0)(5^)6---*|| + +Oct(-1)(70%) +3--4#_5_^|%-4#-|3--4#_5_^|%-4#-| +3--5|6-4#.5_|3--5_3_|6-4#-|| + +(84%)Oct(-1) +&{2*@t?:{3-1-}|@w?:{5---}}| +@t?:{3-1-}|5(1=)2'-4#_2'_5_2'_|@t?:{3-1-|2-}2(1=)6,-*|| + +(90%)Oct(-3) +@b?:{3-1-|5-4#-|3-1-|5-}52| +@b?:{3-1-|5-4#-|3-1-}|2---|| + + +{8*bcbc}|| + +(85%) +{8*3,,_0.%_0.}|| + +Dur(1) +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section G -------------------- + +<:t:>1_5_1'_5_ + +<:v:>1_6b_2b_6b_ + +<:b:>1.%_ + +Dur(1)Seg(1/4) +&054#25.4#.2^|Dur(0)%.2'1'7_^|Dur(1)%54#25.4#.2^|Dur(0)%-2'.5'_^| +%_4'#2'_^%-^|%.5'4'#2'_^|%-1'.7_^|%---*|| + +Oct(-1)(70%) +5--3|2-2'1'|7--5|6-4#-| +3t---|2'-1'-|7-1'.7_^|%:---^|| + +(84%)Oct(-1) +&{3*@t?:{3-1-|5-}@v?:{4#-}}|3m-2M.1M_^|%---*|| + +(90%)Oct(-3) +@b?:{3-1-|5-4#-|3-1-|5-}52| +@b?:{3-1-|5-4#-|3-1-}|2---|| + + +{4*b-b-|b_d=d=d=b=b_b-}|| + +(58%)Stac(1/2, 0) +{4*0---|0_5'=%=%=0_.0-}|| + + +{8*0x0x}|| + +(85%) +{8*3,,_0.%_0.}|| + +Dur(1) +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section H -------------------- + +<:t:>1_5_1'_5_ + +<:s:>1=0= + + +&05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_^|%%_2'.4#_5_^|%.5'(2=)5.5'_6'_| +{3*5'_.5_.5'_^5'(2=)5.6'_}|4#%'_%,_%'%_%,_*|| + +Oct(-1) +7--@s?:{6|7---}|7--@s?:{6|7---}| +7-@s?:{67}|7-@s?:{67}|(60%)5T-(55%)5q-|(50%)2M---|| + +Stac(1/2,0) +&{3*(1-)3m-(1-)1M-|(1-)5,Mi-(1-)[6,12]-}|(Oct:-1)(1-)3m-(1-)1M-|2M---*|| + +(90%)Oct(-3) +Rest(16)| +3-1-|5-4#-|3-1-|2---|| + + +{4*b-b-|b_d=d=d=b=b_b-}|| + +(58%)Stac(1/2, 0) +{4*0---|0_5'=%=%=0_.0-}|| + + +{8*0x0x}|| + +(85%) +{8*3,,0%0}|| + +Dur(1) +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section I -------------------- + +<:t:>1_5_1'_5_ + + +&3m---|2Mi-5M>_.5'>_.4'#>_^|%[562']>--|3m>.1M>_^%-| +3m---|2Mi-5M>_.7h>_.2'T>_|[5,12][562']'>--|1,Mj.%2_5,_2_| +3m.%%.|2M.5,Mj.5'_4'#_|3'_2q=%_.25_(5^)6q|5_.2_.5[562'].| +3m---|2Mi-5M>_.5Mi>_.4'#>_^|%_7h>_%>-^%_7t_^|%_5Mi>.^%-*|| + +(70%) +3m---|2Mi-5Mi-^|%---^|%---| +3m---|2Mi-5Mi-|5M---^|%.1'M>_^%-| +3m---|2Mi-5Mi-^|%---^|%---| +3m---|2Mi-5Mi-|5M---^|%-2M5,Mj|| + +(70%)Oct(-1) +3t---|4#t-5T-|1---|%:---| +3t---|4#t-5T-|[52']:---|1:---| +3t---|4#t-5T-|1---|%:---| +3t---|4#t-5T-|[52']---|1:---|| + +(80%)Oct(-1) +&{(Dur:1)252'5352'5}|@t?:{2-5,-}|{(Dur:1)152'5152'5}|3,o.1,o_^%-| +{(Dur:1)352'5352'5}|@t?:{2-5,-}|{(Dur:1)152'55,52'5}|1,o.%_^%-| +{(Dur:1)352'5352'5}|@t?:{2-5,-}|{(Dur:1)15651565}|@t?:{1-1-}| +{(Dur:1)352'5352'5}|@t?:{2-5,-}|{(Dur:1)152'5152'5|352'51,5,13}*|| + + +{4*{3*x.x_x-}|xb=b=x_x-}|| + +(83%)Dur(1) +{16*07'%00%%0}|| + + +{16*0x0x}|| + +Dur(1) +Rest(32)| +{4*ccppcppp|ppppcppc}|| + +//-------------------- Section J -------------------- + +FadeOut(1) + +<:t:>1_5_1'_5_ + +Oct(1) +&05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_^|%%_2'.4#_5_^|%.%_5'_.4'#_.2'_| +05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_|5T_.5_.5q_.7_.6_5_|2q-4#-^|%---*|| + +Oct(1)(87%) +&05_2'.4#_5_^|%.%_1'_(3~){7=1'=7=}6_5_^|%%_2'.4#_5_^|%.%_5'_.4'#_.2'_*| +Rest(20)|| + + +&{3*@t?:{3-1-|5,-}4,#_2_5_2_}|(Oct:-1)@t?:{3-1-}|2po---^|%---*|| + + +{3*x.x_x-}|xb=b=x_x-| +Rest(20)|| + + +{4*0x0x}| +Rest(20)|| \ No newline at end of file diff --git a/Songs/For_Elise.tm b/Songs/For_Elise.tm new file mode 100644 index 0000000..3040f33 --- /dev/null +++ b/Songs/For_Elise.tm @@ -0,0 +1,81 @@ +// For Elise + +(1=C) (150) (3/4) Light(0.88) + +Dur(1) +3'3b'3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]:---| +3'3b'3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]-07| +1'2'3'--5|4'3'2'--4|3'2'1'--3|2'1'7--3|3'3:3':3'3''3b':|3':3b'3'3b':3':3b'| +3'3b'3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]-07| +1'2'3'--5|4'3'2'--4|3'2'1'--3|2'1'7--3|3'3:3':3'3''3b':|3':3b'3'3b':3':3b'| +3'3b'3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]-0[31']|[41'][351']1---| + +(80%) Oct(-1) +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,_3_6| +01_5_1'|05,_5_7|06,_3_6|03,_3_3'|0--|0--| +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,_3_6| +01_5_1'|05,_5_7|06,_3_6|03,_3_3'|0--|0--| +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,_3_6_[7b1']_|[61']_[57b1']_4_6_1'_6_| + + +Dur(1) Oct(1) +4.3.-2-|7b.6_6543|217b,-6,.7b,_|6,_5,_6,_7b,_1---|23b3--3b|46,1-2_1_7,_1_| Dur(2) +2--7,155,56,57,5|1525351'76543|2542155,56,57,5|1525351'76543| +25423433b37,33b|37,33b(Dur:1)3--7,|33b3--7,|3:3b33b:3:3b| Oct(0) +3'3b'3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]-07| +1'2'3'--5|4'3'2'--4|3'2'1'--3|2'1'7--3|3'3:3':3'3''3b':|3':3b'3'3b':3':3b'| +3'3b'3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]-0-| + +(80%) Oct(-1) Dur(1) +1'647b2'7b|2'7b42'[457b]2'|[457b]2'461'6|1'6461'6|1'6361'6|[22']453'53'| Oct(1) +5,4[13]0-[45]|[35][245][135]0[46],-|[57],-1-0[45]|[35][245][135]0[46],-| +[57],-[5#7],-0-|(Dur:0)0--|0--|0--| Oct(-1) +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,_3_6| +01_5_1'|05,_5_7|06,_3_6|03,_3_3'|0--|0--| +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,:_6,:_6,:_6,:_| + + +0[357b1#']-^|%[462']-|[1#3]'_[24]'_[5#2'4']-|%[61'3']-^| +%[42']-|[31']_[27]_[14#6]-|[16]%[31']|[27][16]-| +0[357b1#']-^|%[462']-|[1#3]'_[24]'_%-|%%-^| +%[53b']-|[42']_[3b1']_[247b]-|[246][245#]-|%[136]-| +0[37]0|0(Dur:Log2(3))6,1361'3'|(Oct:1)217,6,1361'3'| +(Oct:2)217,6,1361'3'|2'1'77b65#54#4|33b21#17,7b,6,5#,| + +(70%) Oct(-2) Dur(1) +6%%%%%|%%%%%%|%%%%%%|%%%%%%| +%%[26]%%%|%%[3b6]%%%|%%[36]%%%|[35#]%6u6%%| +%%%%%%|%%%%%%|%%%%%%|%%7b%%%| +%%%%%%|%%%%%%|%%7%%%|%%1'-0-| Dur(0) Oct(-1) +0[35#]0|06,,0|[61'3']%0| +%%0|%%0|0--| + + +Dur(1) +(3~){5'4#'4'}3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]-07| +1'2'3'--5|4'3'2'--4|3'2'1'--3|2'1'7--3|3'3:3':3'3''3b':|3':3b'3'3b':3':3b'| +3'3b'3'3b'3'7|2'1'6-01|367-03|5#71'-03| +3'3b'3'3b'3'7|2'1'6-01|367-02|1'7[1:6]-0-| + +(80%) Oct(-1) +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,_3_6| +01_5_1'|05,_5_7|06,_3_6|03,_3_3'|0--|0--| +0--|06,_3_6|03,_3_5#|06,_3_6| +0--|06,_3_6|03,_3_5#|06,u-| + + diff --git a/Thulium.nb b/Thulium.nb index 7bfb93b..2bdb367 100644 --- a/Thulium.nb +++ b/Thulium.nb @@ -10,11 +10,11 @@ NotebookFileLineBreakTest NotebookFileLineBreakTest NotebookDataPosition[ 158, 7] -NotebookDataLength[ 11015, 280] +NotebookDataLength[ 11069, 282] NotebookOptionsPosition[ 2673, 78] -NotebookOutlinePosition[ 10928, 279] -CellTagsIndexPosition[ 10835, 273] -WindowTitle->Thulium Music Player 2.3 +NotebookOutlinePosition[ 10982, 281] +CellTagsIndexPosition[ 10889, 275] +WindowTitle->Thulium Music Player 2.4 WindowFrame->ModelessDialog*) (* Beginning of Notebook Content *) @@ -28,11 +28,11 @@ Cell[BoxData[ FontColor->RGBColor[0.1, 0.4, 0.7]], TemplateBox[{1}, "Spacer1"], - StyleBox["\<\"v2.3\"\>", + StyleBox["\<\"v2.4\"\>", FontFamily->"Source Sans Pro", FontSize->24, FontColor->RGBColor[0.3, 0.5, 0.8]]}]], "Title", - CellTags->"$title",ExpressionUUID->"0ac06cd2-7247-475f-9f50-5d0787550bb2"], + CellTags->"$title",ExpressionUUID->"a7100f5c-a6d8-4772-be85-eafe525289d8"], Cell[BoxData[ RowBox[{ @@ -74,7 +74,7 @@ Cell[BoxData[ "LogoButton"], TemplateBox[{4}, "Spacer1"]}]], "Init", - CellTags->"$init",ExpressionUUID->"1344fc7e-8fda-455e-b7da-8c528a24bd82"] + CellTags->"$init",ExpressionUUID->"3d720bdd-bf43-4791-924c-f2e52dfad808"] }, Editable->False, Saveable->False, @@ -95,7 +95,7 @@ WindowMargins->{{229, Automatic}, {Automatic, 32}}, WindowFrame->"ModelessDialog", WindowElements->{}, WindowFrameElements->{"CloseBox", "MinimizeBox", "ZoomBox"}, -WindowTitle->"Thulium Music Player 2.3", +WindowTitle->"Thulium Music Player 2.4", ShowCellBracket->False, Evaluatable->False, CellContext->"Global`", @@ -177,27 +177,29 @@ StyleDefinitions->Notebook[{ TemplateBoxOptions -> {DisplayFunction -> (GraphicsBox[{#3, FilledCurveBox[{ BezierCurve[CompressedData[" -1:eJxTTMoPSmViYGBQAmIQbQwCil0OIuvcH1Zl1BwA8z/3OMyaCQS9tQeqQRJC -/Q6trwN3yLk2wvmKG4oyJjq1wPniN899D17TfuDwV42Yfr8ehzQQKOiCyD/p -gPPfAI1pbc4hmt9/CGigfxScD3bXTDGI+4Lb4Xx5kANrmuF8zRigzpKGAyBv -ibwLgOg/VH2g0Jbr+mKPZIfriwtsuW5XQtQ7JjuAxWdUHgCrs0uGmB+K4AcB -nfVaEI3fWXAASjtAxSH2CVXC+WD/nK6D88H+edoIsa8i8wDYnVbNEH5MIUT+ -e7MDyNjAhIIDDCBwq8WBC+TgWfkQ+862wvng+IrtgPPBdEGXgwfQGes+F8P5 -MPfD+GB77KsO/LtS8VItBMqPrz4ADhek9AAATHMBgw== +1:eJxTTMoPSmViYGBQAmIQbQwCil0OIuvcH1Zl1BwA8z/3OMwEgd7aA9UgCaF+ +h9bXgTvkXBvhfIUNRRkTnVrgfLGb574Hr2k/cPirRky/X49DGggUdEHkn3TA ++W+AxrQ25xDNn3AIaKB/FJy/AOwwMYj7gtvhfDmQA2ua4XygKw59LWk4APKW +yLsAh1SQ/kPVBwptua4v9kh2uLa4wJbrduWBWSDljskOBSDxGZUH0kHq7JIh +5oci+CBnvRZE43cWHAiC0BDz7ZIh9glVwvlg/5yug/P7Qf552uiQD7KvIvOA +JsidVs0Q+2MKIfLfmx1AxgYmFBxgAIFbLQ6c14EOnpUPse9sK5wPjq/YDjif +C0QXdDmAnLHuczGcHwR1P4wPtse+6sC/KxUv1UK6HMDhHF99ACTNhZQeAFPb +AYQ= "]]}], RGBColor[1, 1, 1], FilledCurveBox[{ BezierCurve[CompressedData[" -1:eJxTTMoPSmViYGAwBGIQffirRkz/iUaHQluu64tXlBxA5/cfAgqsbXQAcQsy -Sw7skGt9HZjS6ADk2XKxlxxY5/6wSqSuAaL+QtEBsLqDdQ5A0XXupkUQ/Ytr -HMD6OIog6v9VO4Dt+VV4YNZMINCtdtCMAar8UHjAA6SxvcohDQTeFR4Ai3+p -gOh/UXggCMTQLXcwBgH5ogMgaY09pQ5nzwDBlSKI+jN1DtVA6x9aNBPkg5xr -m1TrsO3z3ysV15oOfAM661BntQNYfFkTRP2ESoj8viaI/aWlUPc2QcIjpgji -f6+WAyBjq5YUORw8tdB126HWA2DxN1C+VTskPKrLHISaD5xa6NQBCe9pVQ5r -ZKJSrAU6IOGxsc7BcsuJsn132yH8pw0Oi1yBLmhuO/AmEGjjQSifu/UAOJz3 -Njj8u1LxUu1BywFDDqBJmxsc3EAO3toCcd+SBgeweG8LxL8k8MHx2VrlAI63 -fcUE+eB08bwKEr+TiiHu31vjsAQofL28GOL+07UO4HCqKT4Ajkfregd5oDN3 -NBVD3HugwQGs7ydUv2AjJLw1Sg6AlMnFN0LsC8NMr5TyAWtplCQ= +1:eJxTTMoPSmViYGAwBGIQffirRkz/iUaHQluu64tXlBxA5084BBRY2+hgB+QW +ZJYc2CnX+jowpdEByLPlYi85sN79YZVIXQNE/YWiA/YgdQfrHICi69xNiw5M +BOlfXOOwA6SPo+jABpD6f9UOIOH+X4UHZs8EAt1qB82Y/kNfPxQe8ARpbK9y +SAOBd4UHtEDiXyog+l8UHggGMXTLHYxBQL7oQBxQWmNPqcMZELhSdABszpk6 +h2qg9Q8tmgnyQc61Tap12Pb575WKa00HvgGddaiz2gEsvqwJon5CJUR+X9OB +IJD9paVQ9zYdALsrpsihAOR/r5YDIGOrlhQ5HDi10HXbodYDYPE3UL5V+wGQ +c2OqyxyEmoEiTh0HwOEwrcphjUxUirVAxwFQcMzcWOdgueVE2b677RD+0waH +Ra5AFzS3HXgdCLTxIJTP3XoAHM57Gxz+Xal4qfag5YAhB9CkzQ0ObiAHb22B +uG9JgwNYvLcF4l8S+CDnF7RWOYC8JbKvmCAfnC6eV0Hid1IxxP17axyWgAKi +vBji/tO1DuBwqik+AI5H63oHkDN3NBVD3HugwQGs7ydUv2CjAyhavmqUHAAp +k4tvhNgXhpleKeUDAIAZlCM= "]]}]}, ImageSize -> 240]& )}], Cell[ StyleData["TextButtonDisplay"], @@ -263,24 +265,24 @@ NBVD3HugwQGs7ydUv2AjJLw1Sg6AlMnFN0LsC8NMr5TyAWtplCQ= (*CellTagsOutline CellTagsIndex->{ "$title"->{ - Cell[604, 21, 421, 13, 140, "Title",ExpressionUUID->"0ac06cd2-7247-475f-9f50-5d0787550bb2", + Cell[604, 21, 421, 13, 140, "Title",ExpressionUUID->"a7100f5c-a6d8-4772-be85-eafe525289d8", CellTags->"$title"]}, "$init"->{ - Cell[1028, 36, 1641, 40, 140, "Init",ExpressionUUID->"1344fc7e-8fda-455e-b7da-8c528a24bd82", + Cell[1028, 36, 1641, 40, 140, "Init",ExpressionUUID->"3d720bdd-bf43-4791-924c-f2e52dfad808", CellTags->"$init"]} } *) (*CellTagsIndex CellTagsIndex->{ - {"$title", 10562, 264}, - {"$init", 10693, 267} + {"$title", 10616, 266}, + {"$init", 10747, 269} } *) (*NotebookFileOutline Notebook[{ -Cell[604, 21, 421, 13, 140, "Title",ExpressionUUID->"0ac06cd2-7247-475f-9f50-5d0787550bb2", +Cell[604, 21, 421, 13, 140, "Title",ExpressionUUID->"a7100f5c-a6d8-4772-be85-eafe525289d8", CellTags->"$title"], -Cell[1028, 36, 1641, 40, 140, "Init",ExpressionUUID->"1344fc7e-8fda-455e-b7da-8c528a24bd82", +Cell[1028, 36, 1641, 40, 140, "Init",ExpressionUUID->"3d720bdd-bf43-4791-924c-f2e52dfad808", CellTags->"$init"] } ] diff --git a/build/.Graphics.wl b/build/.Graphics.wl index f8c600f..cfe114f 100644 --- a/build/.Graphics.wl +++ b/build/.Graphics.wl @@ -2,113 +2,140 @@ BeginPackage["Thulium`Graphics`"]; -SVGPathD::usage = "SVGPathD parses a svg path command."; -CurveMerge::usage = "CurveMerge merges a Bezier curve from segments."; +SVGPath::usage = "SVGPath parses a svg path command."; VertexAssign::usage = "VertexAssign assigns vertices with a coordinate."; progressBar::usage = "Draw a progress bar."; progressSlider::usage = "Draw a progress slider."; progressLocate::usage = "Location to progression"; squareRounded::usage = "Draw a rounded square."; +CleanMessages::usage = "clean messages on the screen"; +MessageDisplay::usage = "display a message on the screen"; +RawDisplay::usage = "display input form of string instead of output form"; +MonitorDisplay::usage = "display a monitor during an evaluating process"; +ProgressDisplay::usage = "display a progress indicator in a monitored process"; + Begin["`Private`"]; -SVGPathD[string_]:=Block[ +SVGPath[string_] := Block[ { - commands, - prev={0,0},this,ctrl, - init={0,0},move, - segments={},points={{0,0}}, - components={Line[{{0,0}}]} + commands, move, + prev = {0, 0}, this = {0, 0}, + init = {0, 0}, controls, + segment = {}, result = {} }, - commands=StringCases[string, - cmd:LetterCharacter~~n:(NumberString|","|WhitespaceCharacter)...:><| - "Name"->cmd, - "Args"->ToExpression/@StringCases[n,NumberString] + commands = StringCases[string, + name: LetterCharacter ~~ args: RegularExpression["[-.,\\d\\s]*"] :> <| + "Name" -> name, + "Args" -> ToExpression /@ StringCases[args, NumberString] |> ]; Do[ - move=If[UpperCaseQ@command[["Name"]],Set,AddTo]; - Switch[ToUpperCase@command[["Name"]], + move = If[UpperCaseQ @ command["Name"], Set, AddTo]; + Switch[ToUpperCase @ command["Name"], "M", - move[this,command[["Args"]]]; - init=this; - If[!MatchQ[components,{Line[{_}]}], - AppendTo[segments,<| - "Points"->points, - "Segment"->components - |>]; - ]; - points={};components={}, + move[this, command[["Args"]]]; + init = this; + If[Length @ segment > 0, + AppendTo[result, {#[[1]], -#[[2]]}& /@ Flatten[ segment, 1]]; + segment = {}; + ], "H", - move[this,{command[["Args",1]],0}], + move[this, {command[["Args", 1]], 0}], "V", - move[this,{0,command[["Args",1]]}], + move[this, {0, command[["Args", 1]]}], "Z", - this=init, + this = init, "L", - move[this,command[["Args"]]], + move[this, command[["Args"]]], "C", - move[this,command[["Args",5;;6]]]; - ctrl=If[UpperCaseQ@command[["Name"]],0,prev]+#&/@Partition[command[["Args"]],2], - _, - Echo@command[["Name"]]; + move[this, command[["Args", 5 ;; 6]]]; + controls = Map[ + If[UpperCaseQ @ command["Name"], 0, prev] + #&, + Partition[command[["Args"]], 2] + ]; ]; - If[MemberQ[Characters["MmZzLlHhVv"],command[["Name"]]], - AppendTo[points,this]; - AppendTo[components,Line[{this}]], - points=Join[points,ctrl]; - AppendTo[components,BezierCurve[ctrl]]; + If[MemberQ[Characters["MmZzLlHhVv"], command["Name"]], + If[Length @ segment > 0, + AppendTo[segment, {this, this, this}], + AppendTo[segment, {this}] + ], + AppendTo[segment, controls] ]; - prev=this, - {command,commands}]; - If[!MatchQ[components,{Line[{_}]}], - AppendTo[segments,<| - "Points"->points, - "Segment"->components - |>]; - ]; - Return[segments]; + prev = this, + {command, commands}]; + If[Length @ segment > 0, AppendTo[result, {#[[1]], -#[[2]]}& /@ Flatten[segment, 1]]]; + Return[result]; ]; -CurveMerge[segment_]:=Block[ - {pts={Level[segment[[1]],1]}}, - Do[ - Switch[Head[component], - Line, - AppendTo[pts,ConstantArray[Level[component,{2}],3]], - BezierCurve, - AppendTo[pts,Level[component,1]] +VertexAssign[vertices_, {pt1x_, pt1y_} -> pos1_, {pt2x_, pt2y_} -> pos2_] := { + ((pos1 - pos2) * ((pt1x - pt2x) * #[[1]] + (pt1y - pt2y) * #[[2]]) + + pos1 * (-pt1x * pt2x + pt2x ^ 2 - pt1y * pt2y + pt2y ^ 2) + + pos2 * (pt1x ^ 2 - pt1x * pt2x + pt1y ^ 2 - pt1y * pt2y) + )/((pt1x - pt2x) ^ 2 + (pt1y - pt2y) ^ 2), +0}& /@ vertices; + +MonitorDisplay[content_] := Style[ + Framed[ + Pane[content, + Scrollbars -> False, + Alignment -> {Center, Center}, + ImageMargins -> {{4, 4}, {4, 4}}, + ImageSize -> {Dynamic @ CurrentValue[EvaluationNotebook[], WindowSize][[1]] / 2 - 200, Automatic} ], - {component,Drop[segment,1]}]; - Return[Flatten[pts,2]]; + Background -> RGBColor[0.96, 0.98, 1], + RoundingRadius -> {8, 8}, + ContentPadding -> True, + FrameStyle -> None + ], + FontFamily -> "Calibri", + FontSize -> 16 +]; + +ProgressDisplay[items_, index_, title_] := MonitorDisplay[ + Column[{ + title, + Graphics[progressBar[(index - 1) / Length[items], 24], ImageSize -> {400, 20}], + Row[{ + "Loading: ", Spacer[2], + items[[index]], Spacer[6], + "(", index, "/", Length[items], ")" + }] + }, Alignment -> Center] ]; -VertexAssign[vertices_,{pt1x_,pt1y_}->pos1_,{pt2x_,pt2y_}->pos2_]:={ - ((pos1-pos2)*((pt1x-pt2x)*#[[1]]+(pt1y-pt2y)*#[[2]]) - +pos1*(-pt1x*pt2x+pt2x^2-pt1y*pt2y+pt2y^2) - +pos2*(pt1x^2-pt1x*pt2x+pt1y^2-pt1y*pt2y) - )/((pt1x-pt2x)^2+(pt1y-pt2y)^2), -0}&/@vertices; - -progressBarShape[l_,r_,t_]:={ - {l,1},{l-t,1},{l-1,t},{l-1,0}, - {l-1,-t},{l-t,-1},{l,-1},{l,-1}, - {r,-1},{r,-1},{r+t,-1},{r+1,-t}, - {r+1,0},{r+1,t},{r+t,1},{r,1} +MessageDisplay[cells_] := Block[{msgCells}, + If[CurrentValue[{StyleDefinitions, ""}] == {}, Return[]]; + SelectionMove[First @ Cells[CellTags -> "$monitor"], After, Cell, AutoScroll -> False]; + NotebookWrite[EvaluationNotebook[], cells]; + NotebookLocate["$title"]; +]; + +CleanMessages[maxCount_] := With[{msgCells = Cells[CellTags -> "$msg"]}, + If[Length @ msgCells > maxCount, NotebookDelete[Drop[msgCells, maxCount]]]; +]; + +RawDisplay[text_] := FormBox[StyleBox["\"" <> text <> "\"", FontFamily -> "Calibri"], "InputForm"]; + +progressBarShape[l_, r_, t_] := { + {l, 1}, {l - t, 1}, {l - 1, t}, {l - 1, 0}, + {l - 1, -t}, {l - t, -1}, {l, -1}, {l, -1}, + {r, -1}, {r, -1}, {r + t, -1}, {r + 1, -t}, + {r + 1, 0}, {r + 1, t}, {r + t, 1}, {r, 1} }; -progressBar[pro_,len_]:=With[ +progressBar[pro_, len_] := With[ { - content=progressBarShape[-len,len*(2pro-1),3/5], - profile=progressBarShape[-len,len,3/5] + content = progressBarShape[-len, len * (2 pro - 1), 3 / 5], + profile = progressBarShape[-len, len, 3 / 5] }, GraphicsGroup[{ - RGBColor["#D0D0F0"],Thickness[1/len/4], - BezierCurve[profile],Line[{{-len,1},{len,1}}], - RGBColor["#F0F0FF"],FilledCurve[{BezierCurve[profile]}], - Texture[Table[{c,1-c,1},{c,0,1,1/256}]], + RGBColor["#D0D0F0"], Thickness[1 / len / 4], + BezierCurve[profile], Line[{{-len, 1}, {len, 1}}], + RGBColor["#F0F0FF"], FilledCurve[{BezierCurve[profile]}], + Texture[Table[{c, 1 - c, 1}, {c, 0, 1, 1 / 256}]], FilledCurve[{BezierCurve[content]}, - VertexTextureCoordinates->VertexAssign[content,{-len,0}->1/5,{len,0}->4/5] + VertexTextureCoordinates -> VertexAssign[content, {-len, 0} -> 1 / 5, {len, 0} -> 4 / 5] ] }] ]; @@ -132,15 +159,17 @@ progressSlider[pro_,len_]:=GraphicsGroup[{ }]; (* basic graphics *) -squareRounded[t_,r_,scheme_]:=If[r==1, +squareRounded[t_, r_, scheme_] := If[r == 1, GraphicsGroup[{ - scheme[["Grounding"]],Disk[{0,0},1-t], - scheme[["Margin"]],Thickness[t],Circle[{0,0},1-t] + scheme["Grounding"], + Disk[{0, 0}, 1 - t], + scheme["Margin"], Thickness[t], + Circle[{0, 0}, 1 - t] }], GraphicsGroup[{ - scheme[["Grounding"]], - Rectangle[{t-1,t-1},{1-t,1-t},RoundingRadius->{r-t,r-t}], - scheme[["Margin"]],Thickness[t],CapForm["Round"], + scheme["Grounding"], + Rectangle[{t - 1, t - 1}, {1 - t, 1 - t}, RoundingRadius -> {r - t, r - t}], + scheme["Margin"], Thickness[t], CapForm["Round"], Circle[{r-1,r-1},r-t,{Pi,3Pi/2}],Circle[{1-r,1-r},r-t,{0,Pi/2}], Circle[{1-r,r-1},r-t,{-Pi/2,0}],Circle[{r-1,1-r},r-t,{Pi/2,Pi}], Line[{{r-1,t-1},{1-r,t-1}}],Line[{{r-1,1-t},{1-r,1-t}}], @@ -153,14 +182,8 @@ End[]; EndPackage[]; -DeclarePackage["Thulium`Graphics`",{ - "SVGPathD", - "CurveMerge", - "VertexAssign", - "progressBar", - "progressSlider", - "progressLocate", - "squareRounded" -}] - DumpSave[$LocalPath <> "library/Package/.Graphics.mx", "Thulium`Graphics`"]; + + +(* ::Input:: *) +(*Clear["Thulium`Graphics`*"];*) diff --git a/build/Assets.wl b/build/Assets.wl index 01b9a60..b876118 100644 --- a/build/Assets.wl +++ b/build/Assets.wl @@ -1,14 +1,23 @@ (* ::Package:: *) -BeginPackage["Thulium`Assets`", {"Thulium`System`"}]; +BeginPackage["Thulium`Assets`", { + "Thulium`System`", + "Thulium`Graphics`" +}]; WindowBackground::usage = "Thulium front end window background"; +ChsFont::usage = "Thulium Music chinese Font"; +EngFont::usage = "Thulium Music english Font"; +StyleDict::usage = "Thulium Style Dict"; Caption::usage = "Thulium front end captions."; Container::usage = "Dialog container framework."; TextLength::usage = "TextLength"; TimeDisplay::usage = "TimeDisplay"; ListSize::usage = "ListSize"; +LogoCloud::usage = "LogoCloud"; +LogoNote::usage = "LogoNote"; + RefreshLanguage::usage = "RefreshLanguage"; TagName::usage = "TagName"; InstName::usage = "InstName"; @@ -24,8 +33,20 @@ imageTags = {"Title", "Painter", "PainterID", "IllustID", "Source", "URL"}; aboutTags = {"Version", "Producer", "Website"}; langList = {"chs", "eng"}; +TooltipDisplay::usage = "TooltipDisplay"; + Begin["`Private`"]; +LogoCloud = SVGPath["M836.15,454.53c90.25,18.32,158.21,98.11,158.21,193.791c0,109.22-88.54,197.729-197.75,197.729h-568.5 +c-122.87,0-222.46-99.6-222.46-222.46c0-96.97,62.07-179.44,148.62-209.9c-0.22-4.15-0.32-8.34-0.32-12.57 +c0-136.5,110.67-247.17,247.18-247.17c91.59,0,171.54,49.82,214.24,123.84c23.55-15.77,51.88-24.97,82.37-24.97 +c81.91,0,148.29,66.41,148.29,148.3c0,18.84-3.511,36.84-9.9,53.41"][[1]]; +LogoNote = SVGPath["M569.07,330.54c0,0-3.4-3.95-12.53-10.1 +c-28.78-19.4-64.45-29.11-98.33-31.92c-10.33-0.86-23.36-1.46-33.73-1.62c-25.17-0.38-53.61,3.05-76.72,14.4L492.81,615.11 +c-22.67-12.301-52.2-18.33-83.75-15.301c-65.69,6.311-115.29,49.521-110.78,96.53c4.51,47,61.43,79.99,127.13,73.69 +c65.69-6.311,115.29-49.53,110.78-96.53c-0.53-5.48-1.771-10.77-3.65-15.83h-0.01L424.34,315.88c6.1-2.72,35.51-4.39,52.38-4.1 +c22.98,0.39,59.32,7.82,69.48,10.78C555.89,325.38,569.07,330.54,569.07,330.54z"][[1]]; + ListSize = 16; WindowBackground = RGBColor[1, 1, 1]; @@ -40,20 +61,22 @@ RefreshLanguage := With[ MsgDict = Association @ Import[langDataPath <> "Messages.json"]; ]; -StyleFont := If[$OperatingSystem === "MacOSX", "\:82f9\:65b9", "\:5fae\:8f6f\:96c5\:9ed1"]; +ChsFont := Once @ If[$OperatingSystem === "MacOSX", "\:82f9\:65b9", "\:5fae\:8f6f\:96c5\:9ed1"]; +EngFont := Once @ If[$OperatingSystem === "MacOSX", "Calibri", "Calibri"]; -StyleDict := <| +StyleDict := Once @ With[{font = If[$OperatingSystem === "MacOSX", "\:82f9\:65b9", "\:5fae\:8f6f\:96c5\:9ed1"]}, <| "None" -> {}, "Text" -> {FontSize -> 20}, - "Title" -> {FontSize -> 32, FontFamily -> StyleFont, FontWeight -> Bold}, - "TitleCmt" -> {FontSize -> 28, FontFamily -> StyleFont, FontWeight -> Bold, FontColor -> GrayLevel[0.4]}, - "Subtitle" -> {FontSize -> 24, FontFamily -> StyleFont, FontWeight -> Bold}, - "BigTitle" -> {FontSize -> 40, FontFamily -> StyleFont, FontWeight -> Bold}, - "BigTitleCmt" -> {FontSize -> 40, FontFamily -> StyleFont, FontWeight -> Bold, FontColor -> GrayLevel[0.4]}, - "SongName" -> {FontSize -> 24, FontFamily -> StyleFont}, - "SongIndex" -> {FontSize -> 22, FontFamily -> StyleFont, FontColor -> GrayLevel[0.2]}, - "SongComment" -> {FontSize -> 22, FontFamily -> StyleFont, FontColor -> GrayLevel[0.4]} -|>; + "Title" -> {FontSize -> 32, FontFamily -> font, FontWeight -> Bold}, + "TitleCmt" -> {FontSize -> 28, FontFamily -> font, FontWeight -> Bold, FontColor -> GrayLevel[0.4]}, + "Subtitle" -> {FontSize -> 24, FontFamily -> font, FontWeight -> Bold}, + "BigTitle" -> {FontSize -> 40, FontFamily -> font, FontWeight -> Bold}, + "BigTitleCmt" -> {FontSize -> 40, FontFamily -> font, FontWeight -> Bold, FontColor -> GrayLevel[0.4]}, + "FormHint" -> {FontSize -> 20, FontFamily -> font, FontSlant -> Plain, FontColor -> GrayLevel[0.4]}, + "SongName" -> {FontSize -> 24, FontFamily -> font}, + "SongIndex" -> {FontSize -> 22, FontFamily -> font, FontColor -> GrayLevel[0.2]}, + "SongComment" -> {FontSize -> 22, FontFamily -> font, FontColor -> GrayLevel[0.4]} +|>]; RenderTemplate[template_, arguments_] := StringReplace[template, { "&" ~~ id: DigitCharacter :> ToString[arguments[[ToExpression @ id]], FormatType -> InputForm], @@ -89,6 +112,26 @@ TimeDisplay[seconds_, levelspec_: 2] := StringRiffle[{ {level, levelspec - 1, 1, -1}] }, ":"]; +TooltipDisplay[content_, tooltip_] := Tooltip[ + content, + Framed[ + Pane[ + tooltip, + ImageSize -> All, + ImageMargins -> {{4, 4}, {4, 4}} + ], + Background -> RGBColor[1, 1, 0.9, 0.8], + FrameStyle -> {1, RGBColor[0.8, 0.8, 0.7, 0.2]}, + RoundingRadius -> {8, 8}, + ContentPadding -> True + ], + TooltipDelay -> 0.1, + TooltipStyle -> { + CellFrame -> {{0, 0}, {0, 0}}, + Background -> RGBColor[0, 0, 0, 0] + } +]; + End[]; EndPackage[]; @@ -103,3 +146,8 @@ DeclarePackage["Thulium`Assets`", { DumpSave[$LocalPath <> "library/Package/Assets.mx", "Thulium`Assets`"]; + + +(* ::Input:: *) +(*Clear["Thulium`Assets`*"]*) +(*Clear["Thulium`Assets`*`*"]*) diff --git a/build/PageSelector.wl b/build/PageSelector.wl index 663d407..07ada6b 100644 --- a/build/PageSelector.wl +++ b/build/PageSelector.wl @@ -115,7 +115,7 @@ PageSelector[Dynamic[page_], pageCount_] := Block[{}, }] ] ] - }, ImageSize -> {500, 60}, Alignment -> Center] + }, ImageSize -> {All, 60}, Alignment -> Center] ]; End[]; diff --git a/build/SetterList.wl b/build/SetterList.wl index 3fa1b78..61b52da 100644 --- a/build/SetterList.wl +++ b/build/SetterList.wl @@ -1,6 +1,8 @@ (* ::Package:: *) -BeginPackage["Thulium`SetterList`", {"Thulium`Graphics`"}]; +BeginPackage["Thulium`SetterList`", { + "Thulium`Graphics`" +}]; SetterList::usage = "SetterList displays a list of items which can be selected."; @@ -8,27 +10,27 @@ Begin["`Private`"]; ListItemColor = <| "Current" -> <| - "Grounding" -> RGBColor[0.96, 0.94, 1], + "Background" -> RGBColor[0.96, 0.94, 1], "Margin" -> RGBColor[0.9, 0.85, 1], "Body" -> RGBColor[0, 0, 0, 1] |>, "Basic" -> <| - "Grounding" -> RGBColor[1, 1, 1, 0], + "Background" -> RGBColor[1, 1, 1, 0], "Margin" -> RGBColor[1, 1, 1, 0], "Body" -> RGBColor[0, 0, 0, 1] |>, "Clicked" -> <| - "Grounding" -> RGBColor[0.1, 0.5, 0.8], + "Background" -> RGBColor[0.1, 0.5, 0.8], "Margin" -> RGBColor[0.1, 0.5, 0.8], "Body" -> RGBColor[0, 0, 0, 1] |>, "Mouseover" -> <| - "Grounding" -> RGBColor[0.98, 0.97, 1], + "Background" -> RGBColor[0.98, 0.97, 1], "Margin" -> RGBColor[0.97, 0.96, 1], "Body" -> RGBColor[0, 0, 0, 1] |>, "Disabled" -> <| - "Grounding" -> RGBColor[1, 1, 1], + "Background" -> RGBColor[1, 1, 1], "Margin" -> RGBColor[0.8, 0.8, 0.8], "Body" -> RGBColor[0.7, 0.7, 0.7] |> @@ -39,29 +41,42 @@ ListItemDisplay[content_, style_, position_] := If[style == "Default", ListItemDisplay[content, "Basic", position], ListItemDisplay[content, "Mouseover", position] ], - With[{scheme = ListItemColor[style]}, GraphicsGroup[{ - scheme["Grounding"], - Rectangle[{-600, -48 * position}, {600, -48 * (position - 1)}], - scheme["Margin"], AbsoluteThickness[1], CapForm["Round"], - Line[{{-600, -48 * position}, {600, -48 * (position - 1)}}], - scheme["Body"], - Inset[content, {0, -48 * position + 24}, Center] - }]] + With[ + { + scheme = ListItemColor[style], + top = -50 * position, + radius = 8 + }, + GraphicsGroup[{ + scheme["Background"], + Rectangle[{-600, top}, {600, top + 48}, RoundingRadius -> radius], + scheme["Margin"], AbsoluteThickness[1], CapForm["Round"], + Line[{{-600 + radius, top}, {600 - radius, top}}], + Line[{{-600 + radius, top + 48}, {600 - radius, top + 48}}], + Line[{{-600, top + radius}, {-600, top + 48 - radius}}], + Line[{{600, top + radius}, {600, top + 48 - radius}}], + Circle[{-600 + radius, top + radius}, radius, {Pi, 3/2 Pi}], + Circle[{-600 + radius, top + 48 - radius}, radius, {1/2 Pi, Pi}], + Circle[{600 - radius, top + radius}, radius, {-1/2 Pi, 0}], + Circle[{600 - radius, top + 48 - radius}, radius, {0, 1/2 Pi}], + scheme["Body"], + Inset[content, {0, top + 24}, Center] + }] + ] ]; -SetterList[Dynamic[sel_], data_] := Row[{ +SetterList[Dynamic[sel_], data_] := Graphics[{Array[With[{item = data[[#]]}, - Dynamic @ If[sel === #, - ListItemDisplay[item, "Current", #], - Module[{style = "Default"}, - EventHandler[Dynamic @ ListItemDisplay[item, style, #], { - "MouseDown" :> (style = "Clicked"), - "MouseUp" :> (style = "Default"; sel = #) - }] - ] + Dynamic @ If[sel === #, + ListItemDisplay[item, "Current", #], + Module[{style = "Default"}, + EventHandler[Dynamic @ ListItemDisplay[item, style, #], { + "MouseDown" :> (style = "Clicked"), + "MouseUp" :> (style = "Default"; sel = #) + }] ] - ]&, Length @ data]}, ImageSize -> Full] -}, Alignment -> Center, ImageSize -> {960, 520}]; + ] + ]&, Length @ data]}, ImageSize -> Full]; End[]; @@ -73,3 +88,7 @@ DeclarePackage["Thulium`SetterList`", {"SetterList"}]; DumpSave[$LocalPath <> "library/Package/SetterList.mx", "Thulium`SetterList`"]; + + +(* ::Input:: *) +(*Pane[SetterList[Dynamic[sel],{Style["1111111111111",36],Style["1111111111111",36],Style["1111111111111",36]}],BaseStyle->Background->White]*) diff --git a/build/SmartButton.wl b/build/SmartButton.wl index 171e041..2edb80a 100644 --- a/build/SmartButton.wl +++ b/build/SmartButton.wl @@ -1,8 +1,12 @@ (* ::Package:: *) -BeginPackage["Thulium`SmartButton`", {"Thulium`Graphics`"}]; +BeginPackage["Thulium`SmartButton`", { + "Thulium`Graphics`", + "Thulium`Assets`" +}]; SmartButton::usage = "a smart display of button."; +SwitchButton::usage = "SwitchButton"; Begin["`Private`"]; @@ -19,7 +23,7 @@ SmartButtonData = <| "Stop"->GraphicsGroup[{ Rectangle[{-0.4,-0.4},{0.4,0.4},RoundingRadius->{0.1,0.1}] }], - "ArrowL"->GraphicsGroup[{ + "Return"->GraphicsGroup[{ Thickness[0.1],CapForm["Round"],JoinForm["Round"], Line[{{-0.4,0},{0.4,0}}], Line[{{0,-0.4},{-0.4,0},{0,0.4}}] @@ -99,12 +103,6 @@ SmartButtonData = <| Disk[{-0.4,0},0.12], Disk[{0.4,0},0.12] }], - "Refresh"->With[{r=0.48},GraphicsGroup[{ - Thickness[0.06],CapForm["Round"],JoinForm["Round"], - Circle[{0,0},r,{0,7/4Pi}], - Line[{{r,0},{r-0.16,0.08}}], - Line[{{r,0},{r+0.08,0.16}}] - }]], "EnterPlaylist"->With[ {t=Pi/8,s={0.12,0.02},h={0,0.64},i={0,0.04},a={-0.36,-0.36},b={0.28,-0.16}}, GraphicsGroup[{ @@ -140,6 +138,21 @@ SmartButtonData = <| Line[{{-0.06,-0.36},{-0.44,-0.36},{-0.44,0.36},{-0.08,0.36},{0,0.24},{0.44,0.24},{0.44,0.12}}] }] ], + "Single" -> With[{x = 0.48, y = 0.2, d = 0.2}, + GraphicsGroup[{ + Thickness[0.08], CapForm["Round"], JoinForm["Round"], + Line[{{-x, y}, {x, y}, {x - d, y + d}}], + Line[{{x, -y}, {-x, -y}, {d - x, - y - d}}] + }] + ], + "Loop" -> With[{r = 0.48}, + GraphicsGroup[{ + Thickness[0.08], CapForm["Round"], JoinForm["Round"], + Circle[{0, 0}, r, {0, 7/4 Pi}], + Line[{{r, 0}, {r - 0.15, 0.1}}], + Line[{{r, 0}, {r + 0.1, 0.15}}] + }] + ], "Directory"->With[{l=0.44,w=0.36,dw=0.12,x1=-0.08,x2=0},GraphicsGroup[{ Thickness[0.06],CapForm["Round"],JoinForm["Round"], Line[{{l,w-dw},{l,-w},{-l,-w},{-l,w},{x1,w},{x2,w-dw},{l,w-dw}}] @@ -181,32 +194,63 @@ SmartButtonDisplay[name_, style_] := If[style == "Default", SmartButtonDisplay[name, "Basic"], SmartButtonDisplay[name, "Mouseover"] ], - With[{scheme = SmartButtonColor[style]}, Graphics[{ - squareRounded[0.06, 1, scheme], - scheme[["Body"]], - SmartButtonData[name] - }]] + With[{scheme = SmartButtonColor[style]}, + Graphics[{ + squareRounded[0.06, 1, scheme], + scheme[["Body"]], + SmartButtonData[name] + }] + ] ]; SetAttributes[SmartButton, HoldRest]; -SmartButton[buttonName_, action_] := DynamicModule[{style = "Default"}, - EventHandler[Dynamic @ SmartButtonDisplay[buttonName, style],{ +SmartButton[name_String, action_] := SmartButton[name, name, action]; +SmartButton[name_String, info_String, action_] := DynamicModule[{style = "Default"}, + EventHandler[Dynamic @ TooltipDisplay[ + SmartButtonDisplay[name, style], + TextDict[info] + ], { "MouseDown" :> (style = "Clicked"), "MouseUp" :> (style = "Default"; action) }] -] +]; + +SwitchButton[source_, items__] := DynamicModule[{style = "Default"}, + PaneSelector[ + #[[1]] -> EventHandler[Dynamic @ TooltipDisplay[ + SmartButtonDisplay[#[[2]], style], + TextDict[#[[2]]] + ], { + "MouseDown" :> (style = "Clicked"), + "MouseUp" :> (style = "Default"; ReleaseHold @ #[[3]]) + }]& /@ {items}, + source + ] +]; End[]; EndPackage[]; -DeclarePackage["Thulium`SmartButton`", {"SmartButton"}]; +DeclarePackage["Thulium`SmartButton`", {"SmartButton", "SwitchButton"}]; DumpSave[$LocalPath <> "library/Package/SmartButton.mx", {"Thulium`SmartButton`"}]; (* ::Input:: *) -(*buttonNames=Keys[buttonData];*) +(*ClearAll["Thulium`SmartButton`*"]*) + + +(* ::Input:: *) +(*buttonNames=Keys[Thulium`SmartButton`Private`SmartButtonData];*) (*buttonNamePaged=Partition[buttonNames,UpTo@Ceiling[Length@buttonNames/Ceiling[Length@buttonNames/9]]];*) -(*Grid[buttonDisplay/@#&/@buttonNamePaged,ItemSize->{6,6},Spacings->{.5,0}]*) +(*Grid[Thulium`SmartButton`Private`SmartButtonDisplay/@#&/@buttonNamePaged,ItemSize->{6,6},Spacings->{.5,0}]*) + + +(* ::Input:: *) +(*stat=1;*) +(*SwitchButton[Dynamic[stat,UpdateInterval->0.1],*) +(*{1,"Play",Hold[stat=2]},*) +(*{2,"Stop",Hold[stat=1]}*) +(*]//List*) diff --git a/build/StyleSheet.wl b/build/StyleSheet.wl index c3cbeb7..e421498 100644 --- a/build/StyleSheet.wl +++ b/build/StyleSheet.wl @@ -89,10 +89,60 @@ AssignTemplate["Message", Function[ FrameStyle -> None ] ]]; - + +AssignTemplate["Setter", Function[ + PaneSelectorBox[{ + True -> #5, + False -> PaneSelectorBox[{ + True -> TemplateBox[{ + TagBox[ + PaneSelectorBox[ + {True -> #6, False -> #7}, + Dynamic @ CurrentValue["MouseButtonTest"] + ], + EventHandlerTag @ {"MouseClicked" :> (#1 = #2)}], + #3, 0.2 + }, ""], + False -> #4 + }, Dynamic @ CurrentValue["MouseOver"]] + }, Dynamic[#1] === #2] +]]; + +AssignTemplate["Setter-Item", Function[ + FrameBox[ + PaneBox[ + StyleBox[#1, + FontFamily -> "Calibri", + FontSize -> 16, + FontColor -> #2 + ], + Scrollbars -> False, + Alignment -> {Center, Center}, + ImageMargins -> {{2, 2}, {2, 2}}, + ImageSize -> {#5, #6} + ], + Background -> #3, + RoundingRadius -> {8, 8}, + ContentPadding -> True, + FrameStyle -> Directive[Thickness[1], #4] + ] +]]; + End[]; EndPackage[]; DumpSave[$LocalPath <> "library/Package/StyleSheet.mx", {"Thulium`StyleSheet`"}]; + + +(* ::Input:: *) +(*ClearAll["Thulium`StyleSheet`*"]*) + + +(* ::Input:: *) +(*SetterBox//Options*) + + +(* ::Input:: *) +(*CurrentValue[{StyleDefinitions,"Setter"}]*) diff --git a/build/Thulium.build.wl b/build/Thulium.build.wl index 6605d79..1c6da02 100644 --- a/build/Thulium.build.wl +++ b/build/Thulium.build.wl @@ -4,33 +4,8 @@ With[ { ThuliumVersion = Thulium`System`$$Version, - LogoCloud = FilledCurveBox[{BezierCurve[{ - {836.15, -454.53}, {926.4, -472.85}, {994.36, -552.64}, {994.36, -648.321}, - {994.36, -757.541}, {905.82, -846.05}, {796.61, -846.05}, {228.11, -846.05}, - {228.11, -846.05}, {228.11, -846.05}, {105.24, -846.05}, {5.65, -746.45}, - {5.65, -623.59}, {5.65, -526.62}, {67.72, -444.15}, {154.27, -413.69}, - {154.05, -409.54}, {153.95, -405.35}, {153.95, -401.12}, {153.95, -264.62}, - {264.62, -153.95}, {401.13, -153.95}, {492.72, -153.95}, {572.67, -203.77}, - {615.37, -277.79}, {638.92, -262.02}, {667.25, -252.82}, {697.74, -252.82}, - {779.65, -252.82}, {846.03, -319.23}, {846.03, -401.12}, - {846.03, -419.96}, {842.519, -437.96}, {836.13, -454.53} - }]}], - - LogoNote = FilledCurveBox[{BezierCurve[{ - {569.07, -330.54}, {569.07, -330.54}, {565.67, -326.59}, {556.54, -320.44}, - {527.76, -301.04}, {492.09, -291.33}, {458.21, -288.52}, {447.88, -287.66}, - {434.85, -287.06}, {424.48, -286.9}, {399.31, -286.52}, {370.87, -289.95}, - {347.76, -301.3}, {492.81, -615.11}, {492.81, -615.11}, {492.81, -615.11}, - {470.14, -602.809}, {440.61, -596.78}, {409.06, -599.809}, {343.37, -606.12}, - {293.77, -649.33}, {298.28, -696.339}, {302.79, -743.339}, {359.71, -776.329}, - {425.41, -770.029}, {491.1, -763.718}, {540.7, -720.499}, {536.19, -673.499}, - {535.66, -668.019}, {534.419, -662.729}, {532.54, -657.669}, {532.53, -657.669}, - {532.53, -657.669}, {532.53, -657.669}, {424.34, -315.88}, {424.34, -315.88}, - {424.34, -315.88}, {430.44, -313.16}, {459.85, -311.49}, {476.72, -311.78}, - {499.7, -312.17}, {536.04, -319.6}, {546.2, -322.56}, - {555.89, -325.38}, {569.07, -330.54}, {569.07, -330.54}, - {569.07, -330.54}, {569.07, -330.54}, {569.07, -330.54} - }]}], + LogoCloud = BezierCurve[Thulium`Assets`LogoCloud], + LogoNote = BezierCurve[Thulium`Assets`LogoNote], InitializeThulium = Hold[ BeginPackage["Thulium`System`"]; @@ -152,7 +127,12 @@ With[ Cell[StyleData["LogoButtonDisplay"], TemplateBoxOptions -> {DisplayFunction -> Function[ - GraphicsBox[{#3, LogoCloud, RGBColor[1, 1, 1], LogoNote}, ImageSize -> 240] + GraphicsBox[{ + #3, + FilledCurveBox[{LogoCloud}], + RGBColor[1, 1, 1], + FilledCurveBox[{LogoNote}] + }, ImageSize -> 240] ]} ], diff --git a/language/chs/GeneralTexts.json b/language/chs/GeneralTexts.json index 1db6ea7..15af6b1 100644 --- a/language/chs/GeneralTexts.json +++ b/language/chs/GeneralTexts.json @@ -1,11 +1,20 @@ { "Thulium": "铥铥播放器", + "Login": "登录", + "LoginTitle": "登 录", + "UserName": "用户名", + "Password": "密码", + "EnterUserName": "输入用户名", + "EnterPassword": "输入密码", + "RememberPassword": "记住密码", + "GuestLogin": "游客登录", "Assistant": "调试助手", "Playlist": "歌单", "AllSongs": "所有歌曲", "Unclassified": "未分类的歌曲", + "EnterPlaylist": "进入歌单", "Settings": "设置", - "About": "关于", + "About": "关于", "ModifySong": "修改歌曲", "AddSong": "添加歌曲", "DeleteSong": "删除歌曲", @@ -22,6 +31,8 @@ "PgNext": "下一页", "PgPrev": "上一页", "SongPath": "歌曲位置", + "Loop": "循环播放", + "Single": "单曲播放", "ChooseIdentity": "选择身份: ", "ChooseLanguage": "选择语言: ", "ChoosePlayer": "选择播放器: ", diff --git a/language/eng/GeneralTexts.json b/language/eng/GeneralTexts.json index 0976881..9640bce 100644 --- a/language/eng/GeneralTexts.json +++ b/language/eng/GeneralTexts.json @@ -1,9 +1,18 @@ { "Thulium": "Thulium Music Player", + "Login": "Login", + "LoginTitle": "Login", + "UserName": "User Name", + "Password": "Password", + "EnterUserName": "Enter User Name", + "EnterPassword": "Enter Password", + "RememberPassword": "Remember Password", + "GuestLogin": "Guest", "Playlist": "Playlist", "Assistant": "Debugging Assistant", "AllSongs": "AllSongs", "Unclassified": "Unclassified", + "EnterPlaylist": "Enter Playlist", "Settings": "Settings", "About": "About", "ModifySong": "Modify Song", @@ -22,6 +31,8 @@ "PgNext": "Next page", "PgPrev": "Previous page", "SongPath": "Song path", + "Loop": "Loop playback", + "Single": "Single playback", "ChooseIdentity": "Choose your identity: ", "ChooseLanguage": "Choose your language: ", "ChoosePlayer": "Choose your player: ", diff --git a/library/Adapter.wl b/library/Adapter.wl index 1bb4a81..192a294 100644 --- a/library/Adapter.wl +++ b/library/Adapter.wl @@ -43,38 +43,38 @@ Thulium`Parse::nosect = "No section was found through part specification `1`."; Thulium`Parse[origin_]:=Thulium`Parse[origin,{1,-1}]; Thulium`Parse[origin_,partspec_]:=Block[ - { - filepath,tempFile,rawData, - sectCount,abspec,startSect,endSect - }, - - Switch[origin, - _String, - If[!FileExistsQ[origin], - Message[Thulium`Parse::nfound,origin];Return[]; - ]; - Switch[ToLowerCase@FileExtension[origin], - (*"json", - rawData=ExternalEvaluate[System`JS,"Parse('"<>origin<>"')"],*) - "tm", - rawData=ExternalEvaluate[System`JS, "new Thulium('"<>StringReplace[origin, "'"->"\\'"]<>"').parse()"], - "", - Message[Thulium`Parse::ext2];Return[], - _, - Message[Thulium`Parse::ext1,FileExtension[origin]];Return[]; - ], - _, - Message[Thulium`Parse::type];Return[]; - ]; - - If[FailureQ[rawData], - Message[Thulium`Parse::failure]; - Echo[Level[Level[rawData,1][[2,"StackTrace"]],1][[1]]]; - Return[]; - ]; - - sectCount=Length@rawData; - abspec=If[#<0,sectCount+1+#,#]&; + { + filepath,tempFile,rawData, + sectCount,abspec,startSect,endSect + }, + + Switch[origin, + _String, + If[!FileExistsQ[origin], + Message[Thulium`Parse::nfound,origin];Return[]; + ]; + Switch[ToLowerCase@FileExtension[origin], + (*"json", + rawData=ExternalEvaluate[System`JS,"Parse('"<>origin<>"')"],*) + "tm", + rawData=ExternalEvaluate[System`JS, "new Thulium('"<>StringReplace[origin, "'"->"\\'"]<>"').parse()"], + "", + Message[Thulium`Parse::ext2];Return[], + _, + Message[Thulium`Parse::ext1,FileExtension[origin]];Return[]; + ], + _, + Message[Thulium`Parse::type];Return[]; + ]; + + If[FailureQ[rawData], + Message[Thulium`Parse::failure]; + Echo[Level[Level[rawData,1][[2,"StackTrace"]],1][[1]]]; + Return[]; + ]; + + sectCount=Length@rawData; + abspec=If[#<0,sectCount+1+#,#]&; Switch[partspec, {_Integer,_Integer}, {startSect,endSect}=abspec/@partspec, @@ -89,10 +89,10 @@ Thulium`Parse[origin_,partspec_]:=Block[ ]; If[startSect>endSect, - Message[Thulium`Parse::nosect,partspec];Return[], - Return[rawData[[startSect;;endSect]]]; + Message[Thulium`Parse::nosect,partspec];Return[], + Return[rawData[[startSect;;endSect]]]; ]; - + ]; @@ -101,32 +101,32 @@ Thulium`Parse[origin_,partspec_]:=Block[ EventConstruct[trackData_,startTime_]:=If[MemberQ[instList,trackData[["Instrument"]]], - <| - "Inst"->instDict[[trackData[["Instrument"]]]], - "Note"->#Pitch+60, - "Start"->startTime+#StartTime, - "End"->startTime+#StartTime+#Duration, - "Vol"->#Volume - |>&, - <| - "Inst"->128, - "Note"->percDict[[trackData[["Instrument"]]]], - "Start"->startTime+#StartTime, - "End"->startTime+#StartTime+#Duration, - "Vol"->#Volume - |>& + <| + "Inst"->instDict[[trackData[["Instrument"]]]], + "Note"->#Pitch+60, + "Start"->startTime+#StartTime, + "End"->startTime+#StartTime+#Duration, + "Vol"->#Volume + |>&, + <| + "Inst"->128, + "Note"->percDict[[trackData[["Instrument"]]]], + "Start"->startTime+#StartTime, + "End"->startTime+#StartTime+#Duration, + "Vol"->#Volume + |>& ]/@trackData[["Content"]]; TrackConstruct[inst_,chan_,events_]:=Sound`MIDITrack[{ - Sound`MIDIEvent[0,"SetTempo","Tempo"->1000000], - Sound`MIDIEvent[0,"ProgramCommand","Channel"->chan,"Value"->If[inst==128,0,inst]], - Sequence@@(Sound`MIDIEvent[ - Floor[#Time], - If[#Event==1,"NoteOn","NoteOff"], - "Note"->#Note, - "Channel"->chan, - "Velocity"->#Velocity - ]&/@SortBy[events,{#Event&,#Time&}]) + Sound`MIDIEvent[0,"SetTempo","Tempo"->1000000], + Sound`MIDIEvent[0,"ProgramCommand","Channel"->chan,"Value"->If[inst==128,0,inst]], + Sequence@@(Sound`MIDIEvent[ + Floor[#Time], + If[#Event==1,"NoteOn","NoteOff"], + "Note"->#Note, + "Channel"->chan, + "Velocity"->#Velocity + ]&/@SortBy[events,{#Event&,#Time&}]) }]; $Resolution = 48; @@ -134,39 +134,39 @@ MIDIConstruct::channel = "The amount of channels exceeds 16. Some channels may b MIDIConstruct::instid = "The sound consists of instrument with ID exceeding 128, thus cannot be transferred to MIDI."; MIDIConstruct[musicClip_,rate_]:=Block[ - { - channelData,channelMap=<||>, - duration - }, - If[rate>0, - channelData=GroupBy[musicClip,#Inst&->({ - <|"Time"->$Resolution*#Start/rate,"Note"->#Note,"Velocity"->Floor[127*#Vol],"Event"->1|>, - <|"Time"->$Resolution*#End/rate,"Note"->#Note,"Velocity"->0,"Event"->0|> - }&)], - (* upend *) - duration=Max[#End&/@musicClip]; - channelData=GroupBy[musicClip,#Inst&->({ - <|"Time"->$Resolution*(duration+#End/rate),"Note"->#Note,"Velocity"->Floor[127*#Vol],"Event"->1|>, - <|"Time"->$Resolution*(duration+#Start/rate),"Note"->#Note,"Velocity"->0,"Event"->0|> - }&)]; - ]; - Do[ - If[instID==128, - AppendTo[channelMap,instID->9], - AppendTo[channelMap,instID->LengthWhile[ - Range[0,Length@channelData],MemberQ[Append[Values@channelMap,9],#]& - ]]; - ], - {instID,Keys@channelData}]; - Return[Sound`MIDISequence[ - KeyValueMap[TrackConstruct[#1,#2,Flatten[channelData[[Key[#1]]],1]]&,channelMap], - "DivisionType"->"PPQ", - "Resolution"->$Resolution - ]]; + { + channelData,channelMap=<||>, + duration + }, + If[rate>0, + channelData=GroupBy[musicClip,#Inst&->({ + <|"Time"->$Resolution*#Start/rate,"Note"->#Note,"Velocity"->Floor[127*#Vol],"Event"->1|>, + <|"Time"->$Resolution*#End/rate,"Note"->#Note,"Velocity"->0,"Event"->0|> + }&)], + (* upend *) + duration=Max[#End&/@musicClip]; + channelData=GroupBy[musicClip,#Inst&->({ + <|"Time"->$Resolution*(duration+#End/rate),"Note"->#Note,"Velocity"->Floor[127*#Vol],"Event"->1|>, + <|"Time"->$Resolution*(duration+#Start/rate),"Note"->#Note,"Velocity"->0,"Event"->0|> + }&)]; + ]; + Do[ + If[instID==128, + AppendTo[channelMap,instID->9], + AppendTo[channelMap,instID->LengthWhile[ + Range[0,Length@channelData],MemberQ[Append[Values@channelMap,9],#]& + ]]; + ], + {instID,Keys@channelData}]; + Return[Sound`MIDISequence[ + KeyValueMap[TrackConstruct[#1,#2,Flatten[channelData[[Key[#1]]],1]]&,channelMap], + "DivisionType"->"PPQ", + "Resolution"->$Resolution + ]]; ]; -(* ::Subsubsection:: *) +(* ::Subsubsection::Closed:: *) (*Adapter*) @@ -186,84 +186,84 @@ The contents of \!\(\*StyleBox[\"options\",\"TI\"]\) can be the following: \!\(\*RowBox[{\"\t\",\"Format\",\"\t\",\"\t\",\"Audio\",\"\t\",\"\t\",\"Adapting format\"}]\)"; Adapt[rawData_,OptionsPattern[AdaptingOptions]]:=Switch[OptionValue["Format"], - "MIDI",Thulium`MIDIAdapt[rawData,OptionValue[Keys@AdaptingOptions]], - "Audio",Thulium`AudioAdapt[rawData,OptionValue[Keys@AdaptingOptions]], - _,Message[Adapt::format,OptionValue["Format"]];Return[]; + "MIDI",Thulium`MIDIAdapt[rawData,OptionValue[Keys@AdaptingOptions]], + "Audio",Thulium`AudioAdapt[rawData,OptionValue[Keys@AdaptingOptions]], + _,Message[Adapt::format,OptionValue["Format"]];Return[]; ]; MusicPlay[rawData_,OptionsPattern[AdaptingOptions]]:=Switch[OptionValue["Format"], - "MIDI",Sound`EmitMIDI@Thulium`MIDIAdapt[rawData,OptionValue[Keys@AdaptingOptions]], - "Audio",AudioPlay@Thulium`AudioAdapt[rawData,OptionValue[Keys@AdaptingOptions]], - _,Message[Adapt::format,OptionValue["Format"]];Return[]; + "MIDI",Sound`EmitMIDI@Thulium`MIDIAdapt[rawData,OptionValue[Keys@AdaptingOptions]], + "Audio",AudioPlay@Thulium`AudioAdapt[rawData,OptionValue[Keys@AdaptingOptions]], + _,Message[Adapt::format,OptionValue["Format"]];Return[]; ]; Thulium`MIDIAdapt[rawData_,OptionsPattern[AdaptingOptions]]:=Block[ { - duration=0,musicClip={} + duration=0,musicClip={} }, - If[!ListQ[rawData],Return[]]; - If[!Through[(Positive||Negative)@OptionValue["Rate"]], - Message[Adapt::invrate,OptionValue["Rate"]];Return[]; - ]; - Do[ - AppendTo[musicClip,Table[ - EventConstruct[trackData,duration], - {trackData,sectionData[["Tracks"]]}]]; - duration+=Max[sectionData[["Tracks",All,"Meta","Duration"]]], - {sectionData,rawData}]; - Return[MIDIConstruct[Flatten@musicClip,OptionValue["Rate"]]]; + If[!ListQ[rawData],Return[]]; + If[!Through[(Positive||Negative)@OptionValue["Rate"]], + Message[Adapt::invrate,OptionValue["Rate"]];Return[]; + ]; + Do[ + AppendTo[musicClip,Table[ + EventConstruct[trackData,duration], + {trackData,sectionData[["Tracks"]]}]]; + duration+=Max[sectionData[["Tracks",All,"Meta","Duration"]]], + {sectionData,rawData}]; + Return[MIDIConstruct[Flatten@musicClip,OptionValue["Rate"]]]; ]; Thulium`AudioAdapt[rawData_,OptionsPattern[AdaptingOptions]]:=Block[ { - duration=0,groups, - musicClips={},targetClip, - compactData,clipUsed, - output=0,clipCount,musicClip + duration=0,groups, + musicClips={},targetClip, + compactData,clipUsed, + output=0,clipCount,musicClip }, - If[!ListQ[rawData],Return[]]; - If[!Through[(Positive||Negative)@OptionValue["Rate"]], - Message[Adapt::invrate,OptionValue["Rate"]];Return[]; - ]; - Do[ - clipUsed={}; - groups=GatherBy[sectionData["Tracks"],#Effects[[{"FadeIn","FadeOut"}]]&]; - Do[ - compactData=Flatten@Table[ - EventConstruct[trackData,duration], - {trackData,group}]; - targetClip=If[group[[1,"Effects","FadeIn"]]==0, - LengthWhile[Range@Length@musicClips,Or[ - musicClips[[#,"FadeOut"]]>0, - MemberQ[clipUsed,#] - ]&]+1, - Length@musicClips+1 - ]; - AppendTo[clipUsed,targetClip]; - If[targetClip>Length@musicClips, - AppendTo[musicClips,<| - "FadeIn"->group[[1,"Effects","FadeIn"]], - "FadeOut"->group[[1,"Effects","FadeOut"]], - "Events"->{compactData} - |>], - musicClips[[targetClip,"FadeOut"]]=group[[1,"Effects","FadeOut"]]; - AppendTo[musicClips[[targetClip,"Events"]],compactData]; - ], - {group,groups}]; - duration+=Max[sectionData[["Tracks",All,"Meta","Duration"]]], - {sectionData,rawData}]; - - output=Total@Table[ - AudioFade[ - Sound@MIDIConstruct[Flatten@musicClip[["Events"]],OptionValue["Rate"]], - If[OptionValue["Rate"]>0, - {musicClip[["FadeIn"]],musicClip[["FadeOut"]]}/OptionValue["Rate"], - {musicClip[["FadeOut"]],musicClip[["FadeIn"]]}/(-OptionValue["Rate"]) - ] - ], - {musicClip,musicClips}]; - - Return[output]; + If[!ListQ[rawData],Return[]]; + If[!Through[(Positive||Negative)@OptionValue["Rate"]], + Message[Adapt::invrate,OptionValue["Rate"]];Return[]; + ]; + Do[ + clipUsed={}; + groups=GatherBy[sectionData["Tracks"],#Effects[[{"FadeIn","FadeOut"}]]&]; + Do[ + compactData=Flatten@Table[ + EventConstruct[trackData,duration], + {trackData,group}]; + targetClip=If[group[[1,"Effects","FadeIn"]]==0, + LengthWhile[Range@Length@musicClips,Or[ + musicClips[[#,"FadeOut"]]>0, + MemberQ[clipUsed,#] + ]&]+1, + Length@musicClips+1 + ]; + AppendTo[clipUsed,targetClip]; + If[targetClip>Length@musicClips, + AppendTo[musicClips,<| + "FadeIn"->group[[1,"Effects","FadeIn"]], + "FadeOut"->group[[1,"Effects","FadeOut"]], + "Events"->{compactData} + |>], + musicClips[[targetClip,"FadeOut"]]=group[[1,"Effects","FadeOut"]]; + AppendTo[musicClips[[targetClip,"Events"]],compactData]; + ], + {group,groups}]; + duration+=Max[sectionData[["Tracks",All,"Meta","Duration"]]], + {sectionData,rawData}]; + + output=Total@Table[ + AudioFade[ + Sound@MIDIConstruct[Flatten@musicClip[["Events"]],OptionValue["Rate"]], + If[OptionValue["Rate"]>0, + {musicClip[["FadeIn"]],musicClip[["FadeOut"]]}/OptionValue["Rate"], + {musicClip[["FadeOut"]],musicClip[["FadeIn"]]}/(-OptionValue["Rate"]) + ] + ], + {musicClip,musicClips}]; + + Return[output]; ]; @@ -314,7 +314,7 @@ Thulium`AudioAdapt[rawData_,OptionsPattern[AdaptingOptions]]:=Block[ (* ::Input:: *) (*AudioStop[];AudioPlay[#[[2]]]&@*) (*EchoFunction["time: ",#[[1]]&]@*) -(*Timing[Thulium`AudioAdapt[Thulium`Parse[$LocalPath<>"Songs/Those_Years.tm",{1,2}],"Rate"->1.2]];*) +(*Timing[Thulium`AudioAdapt[Thulium`Parse[$LocalPath<>"Songs/For_Elise.tm",{4}],"Rate"->1]];*) (* ::Input:: *) diff --git a/library/Assets/Controls/Logo.wl b/library/Assets/Controls/Logo.wl deleted file mode 100644 index 9e94c85..0000000 --- a/library/Assets/Controls/Logo.wl +++ /dev/null @@ -1,32 +0,0 @@ -(* ::Package:: *) - -(* QYMP Logo *) -LogoCloud="M836.15,454.53c90.25,18.32,158.21,98.11,158.21,193.791c0,109.22-88.54,197.729-197.75,197.729h-568.5 -c-122.87,0-222.46-99.6-222.46-222.46c0-96.97,62.07-179.44,148.62-209.9c-0.22-4.15-0.32-8.34-0.32-12.57 -c0-136.5,110.67-247.17,247.18-247.17c91.59,0,171.54,49.82,214.24,123.84c23.55-15.77,51.88-24.97,82.37-24.97 -c81.91,0,148.29,66.41,148.29,148.3c0,18.84-3.511,36.84-9.9,53.41"; -LogoNote="M569.07,330.54c0,0-3.4-3.95-12.53-10.1 -c-28.78-19.4-64.45-29.11-98.33-31.92c-10.33-0.86-23.36-1.46-33.73-1.62c-25.17-0.38-53.61,3.05-76.72,14.4L492.81,615.11 -c-22.67-12.301-52.2-18.33-83.75-15.301c-65.69,6.311-115.29,49.521-110.78,96.53c4.51,47,61.43,79.99,127.13,73.69 -c65.69-6.311,115.29-49.53,110.78-96.53c-0.53-5.48-1.771-10.77-3.65-15.83h-0.01L424.34,315.88c6.1-2.72,35.51-4.39,52.38-4.1 -c22.98,0.39,59.32,7.82,69.48,10.78C555.89,325.38,569.07,330.54,569.07,330.54z"; - - -logo=Scale[{ - RGBColor["#00A0E9"], - FilledCurve[{BezierCurve[CurveMerge[#Segment]]}]&[SVGPathD[LogoCloud][[1]]], - RGBColor["#FFFFFF"], - FilledCurve[{BezierCurve[CurveMerge[#Segment]]}]&[SVGPathD[LogoNote][[1]]] -},{1,-1}]; - - -(* ::Input:: *) -(*Graphics[{Scale[{*) -(*Texture[Table[{c,1-c,1},{c,0,1,1/256}]],*) -(*FilledCurve[{BezierCurve[CurveMerge[#Segment]]},*) -(*VertexTextureCoordinates->VertexAssign[CurveMerge[#Segment],{0,0}->0,{1000,0}->1]*) -(*]&[SVGPathD[LogoCloud][[1]]],*) -(*White,*) -(*FilledCurve[{BezierCurve[CurveMerge[#Segment]]}*) -(*]&[SVGPathD[LogoNote][[1]]]},*) -(*{1,-1}]}]*) diff --git a/library/Assets/Controls/color.json b/library/Assets/Controls/color.json deleted file mode 100644 index cc6bda5..0000000 --- a/library/Assets/Controls/color.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "StyleColor": { - "Default": "#000000", - "Background": "#F9F9F9", - "Comment": "#707070", - "Index": "#303030" - }, - "ButtonColor": { - "Basic": { - "Grounding": "#F9F9F9", - "Margin": "#00AFF0", - "Body": "#00AFF0" - }, - "Clicked": { - "Grounding": "#00AFF0", - "Margin": "#00AFF0", - "Body": "#F9F9F9" - }, - "Mouseover": { - "Grounding": "#AAE8FF", - "Margin": "#00AFF0", - "Body": "#00AFF0" - }, - "Disabled": { - "Grounding": "#F9F9F9", - "Margin": "#C8C8C8", - "Body": "#C8C8C8" - } - }, - "PageSelectorColor": { - "Current": { - "Grounding": "#1979CA", - "Margin": "#1979CA", - "Body": "#F9F9F9" - }, - "Basic": { - "Grounding": "#F9F9F9", - "Margin": "#1979CA", - "Body": "#1979CA" - }, - "Clicked": { - "Grounding": "#1979CA", - "Margin": "#1979CA", - "Body": "#F9F9F9" - }, - "Mouseover": { - "Grounding": "#9BCBF2", - "Margin": "#1979CA", - "Body": "#1979CA" - }, - "Disabled": { - "Grounding": "#F9F9F9", - "Margin": "#C8C8C8", - "Body": "#C8C8C8" - } - } -} \ No newline at end of file diff --git a/library/Assets/Controls/style.json b/library/Assets/Controls/style.json deleted file mode 100644 index fa598ff..0000000 --- a/library/Assets/Controls/style.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "None": {}, - "Text": {"Size": 20}, - "Title": {"Size": 32, "Weight": "Bold", "Family": "微软雅黑"}, - "TitleCmt": {"Size": 28, "Weight": "Bold", "Family": "微软雅黑", "Color": "Comment"}, - "Subtitle": {"Size": 24, "Weight": "Bold", "Family": "微软雅黑"}, - "BigTitle": {"Size": 40, "Weight": "Bold", "Family": "微软雅黑"}, - "BigTitleCmt": {"Size": 40, "Weight": "Bold", "Family": "微软雅黑", "Color": "Comment"}, - "SongName": {"Size": 24, "Family": "微软雅黑"}, - "SongIndex": {"Size": 22, "Family": "微软雅黑", "Color": "Index"}, - "SongComment": {"Size": 22, "Family": "微软雅黑", "Color": "Comment"} -} \ No newline at end of file diff --git a/library/Assets/Player.wl b/library/Assets/Player.wl deleted file mode 100644 index e588cc5..0000000 --- a/library/Assets/Player.wl +++ /dev/null @@ -1,134 +0,0 @@ -(* ::Package:: *) - -BeginPackage["Thulium`Interface`Player`", { - "Thulium`System`", - "Thulium`Assets`", - "Thulium`Graphics`", - "Thulium`SmartButton`" -}]; - -Player::usage = "Thulium Music Player Interface"; - -Begin["`Private`"]; - -PlayerControls[audio_] := Module[ - { - stream = AudioPlay[audio], time, - duration = QuantityMagnitude[Duration[audio], "Seconds"] - }, - time := QuantityMagnitude[stream["Position"], "Seconds"]; - With[{StatusAlias = StatusAlias}, Column[{ - Row[{ - Column[{Style[Dynamic[TimeDisplay[time]], 20], Spacer[1]}], - Spacer[7], - Magnify[EventHandler[ - Dynamic[Graphics[{progressSlider[time / duration, 16]}]], - {"MouseDragged" :> (stream["Position"] = duration * progressLocate[16])} - ], 3.6], - Spacer[8], - Column[{Style[TimeDisplay[time], 20], Spacer[1]}] - }, ImageSize -> Full, Alignment -> Center], - Row[{ - Module[{style = "Default"}, - Dynamic @ Switch[stream[StatusAlias], - "Playing",EventHandler[SmartButton["Pause", style], { - "MouseDown" :> (style = "Clicked"), - "MouseUp" :> (style = "Default"; stream[StatusAlias] = "Paused") - }], - "Paused"|"Stopped",EventHandler[SmartButton["Play", style], { - "MouseDown" :> (style = "Clicked"), - "MouseUp" :> (style = "Default"; stream[StatusAlias] = "Playing") - }] - ] - ], - Spacer[20], - Module[{style = "Default"}, - EventHandler[Dynamic@SmartButton["Stop",style],{ - "MouseDown" :> (style = "Clicked"), - "MouseUp" :> (style = "Default"; stream[StatusAlias] = "Stopped"; stream["Position"] = 0) - }] - ], - Spacer[20], - Module[{style = "Default"}, - EventHandler[Dynamic@SmartButton["ArrowL", style], { - "MouseDown" :> (style = "Clicked"), - "MouseUp" :> (style = "Default"; AudioStop[]; DialogReturn[Thulium`Playlist[Thulium`CurrentPlaylist]]) - }] - ] - }, ImageSize -> {300, 60}, Alignment -> Center] - }, Alignment -> Center] -]]; - -Player[song_]:=Block[ - { - image, audio, imageExist=False, aspectRatio - }, - Quiet @ Check[ - audio = Import[$DataPath <> "Buffer/" <> song <> ".buffer", "MP3"], - Return[Thulium`Playlist[Thulium`CurrentPlaylist]], - Import::nffil]; - AudioStop[]; - If[SongIndex[song, "Image"] != "", - imageExist = True; - image = Import[$DataPath <> "Images/" <> SongIndex[song, "Image"]]; - aspectRatio = ImageAspectRatio[image]; - ]; - CreateDialog[Row[{ - If[imageExist,Row[{Spacer[48],Column[{Spacer[{40,40}], - Tooltip[ImageEffect[Image[image,ImageSize->Piecewise[{ - {{Automatic,600},aspectRatio>2}, - {{480,Automatic},aspectRatio<1/2}, - {{Automatic,400},aspectRatio<=1&&aspectRatio>1/2}, - {{360,Automatic},aspectRatio>1&&aspectRatio<2} - }]],{"FadedFrame"}], - If[ImageIndex[[SongIndex[[song,"Image"]]]]!=<||>, - Column[If[KeyExistsQ[ImageIndex[[SongIndex[[song,"Image"]]]],#], - TagName[[#]]<>": "<>ImageIndex[[SongIndex[[song,"Image"]],#]], - Nothing - ]&/@imageTags], - TextDict[["NoImageInfo"]] - ] - ], - Spacer[{40,40}]}]}],Nothing],Spacer[48], - Column[Join[{Spacer[{60,60}], - If[SongIndex[[song,"Comment"]]!="", - If[TextLength@SongIndex[[song,"Comment"]]>16, - Column,Row - ][{ - Caption[SongIndex[[song,"SongName"]],"Title"], - Caption[" ("<>SongIndex[[song,"Comment"]]<>")","TitleCmt"] - },Alignment->Center], - Caption[SongIndex[[song,"SongName"]],"Title"] - ], - Spacer[1], - Column[If[SongIndex[[song,#]]!="", - Caption[TagName[[#]]<>": "<>SongIndex[[song,#]],"Text"], - Nothing - ]&/@{"Origin","Composer","Lyricist","Adapter"},Alignment->Center], - Spacer[1], - If[SongIndex[[song,"Abstract"]]!="", - Column[Caption[#,"Text"]&/@StringSplit[SongIndex[[song,"Abstract"]],"\n"],Center], - Nothing - ], - Spacer[1]}, - {PlayerControls[audio]}, - {Spacer[{60,60}]} - ],Alignment->Center,ItemSize->Full], - Spacer[48]},Alignment->Center,ImageSize->Full], - Background -> WindowBackground, - WindowTitle -> TextDict["Playing"]<>": "<>SongIndex[song,"SongName"]]; -]; - -End[]; - -EndPackage[]; - -Thulium`Player = Thulium`Interface`Player`Player; - - -(* ::Input:: *) -(*AudioStop[];*) - - -(* ::Input:: *) -(*Thulium`Player["Touhou/Oriental_Blood"]*) diff --git a/library/Assets/newPlaylist.wl b/library/Assets/newPlaylist.wl deleted file mode 100644 index 6eaf6a1..0000000 --- a/library/Assets/newPlaylist.wl +++ /dev/null @@ -1,85 +0,0 @@ -(* ::Package:: *) - -BeginPackage["Thulium`Interface`newPlaylist`", { - "Thulium`System`", - "Thulium`Assets`", - "Thulium`SmartButton`", - "Thulium`PageSelector`" -}]; - -newPlaylist::usage = "newPlaylist"; - -Begin["`Private`"]; - -newPlaylist[playlist_] := Block[ - {info, length, songList, indexList, pageCount}, - info = PlaylistIndex[playlist]; - length = Length @ info["SongList"]; - pageCount = Ceiling[length / ListSize]; - songList = Partition["Song" /. info["SongList"], UpTo @ Ceiling[length / pageCount]]; - indexList = Partition["Index" /. info["SongList"], UpTo @ Ceiling[length / pageCount]]; - If[Thulium`PageIndex[playlist] > pageCount, Thulium`PageIndex[playlist] = pageCount]; - Module[ - {page = Thulium`PageIndex[playlist], index = 1}, - CreateDialog[ - Container[With[ - { - songList = songList, pageCount = pageCount, indexList = indexList, - indexWidth = info["IndexWidth"], - $Epi = Unevaluated[Thulium`PageIndex[playlist] = Dynamic[page]] - }, - Column[{ - Row[{ - Row[{ - Caption[info[["Title"]], "BigTitle"] - }, Alignment -> Left, ImageSize -> 400], - Row[{ - SmartButton["Play", DialogReturn[$Epi; Thulium`Player[songList[[page, index]]]]], - Spacer[10], - SmartButton["ArrowL", DialogReturn[$Epi; Thulium`homepage]] - }, Alignment -> Right, ImageSize -> {400, 60}] - }], - If[info["Comment"] == "", Nothing, - Row[{ - Caption[info[["Comment"]], "Subtitle"] - }, Alignment -> Left, ImageSize -> 800] - ], - Spacer[20], - Dynamic[ - SetterList[Dynamic[index], Table[ - Row[{ - Row[{ - Spacer[8], - If[indexWidth > 0, - Row[{ - Caption[indexList[[page, id]], "SongIndex"], - Spacer[16] - }, ImageSize -> indexWidth, Alignment -> Center], - Spacer[4] - ], - Caption[SongIndex[songList[[page, id]], "SongName"], "SongName"] - }, Alignment -> Left, ImageSize -> 480], - Row[{ - Row[{"Right"}, Alignment -> Center], - Spacer[8] - }, Alignment -> Right, ImageSize -> 480] - }, Alignment -> Center, ImageSize -> {960, 32}], - {id, Length @ songList[[page]]}]], - TrackedSymbols :> {page}], - Spacer[20], - PageSelector[Dynamic[page], pageCount] - }, Center] - ], 100, 40], - WindowTitle -> TagName[info["Type"]] <> " - " <> info["Title"], - Background -> WindowBackground - ]; - ]; -]; - -End[]; - -EndPackage[]; - - -(* ::Input:: *) -(*Thulium`Interface`newPlaylist`newPlaylist["All"];*) diff --git a/library/Initialization.wl b/library/Initialization.wl index a394ee4..5059d09 100644 --- a/library/Initialization.wl +++ b/library/Initialization.wl @@ -24,58 +24,9 @@ StatusAlias::usage = "alias for \"Status\" as a property of AudioStream"; InitializePackage::usage = "initialize all packages"; InitializeParser::usage = "initialize Thulium Music parser"; -CleanMessages::usage = "clean messages on the screen"; -MessageDisplay::usage = "display a message on the screen"; -RawDisplay::usage = "display input form of string instead of output form"; -MonitorDisplay::usage = "display a monitor during an evaluating process"; -ProgressDisplay::usage = "display a progress indicator in a monitored process"; - Begin["`Private`"]; -MonitorDisplay[content_] := Style[ - Framed[ - Pane[content, - Scrollbars -> False, - Alignment -> {Center, Center}, - ImageMargins -> {{4, 4}, {4, 4}}, - ImageSize -> {Dynamic @ CurrentValue[EvaluationNotebook[], WindowSize][[1]] / 2 - 200, Automatic} - ], - Background -> RGBColor[0.96, 0.98, 1], - RoundingRadius -> {8, 8}, - ContentPadding -> True, - FrameStyle -> None - ], - FontFamily -> "Calibri", - FontSize -> 16 -]; - -ProgressDisplay[items_, index_, title_] := MonitorDisplay[ - Column[{ - title, - Graphics[progressBar[(index - 1) / Length[items], 24], ImageSize -> {400, 20}], - Row[{ - "Loading: ", Spacer[2], - items[[index]], Spacer[6], - "(", index, "/", Length[items], ")" - }] - }, Alignment -> Center] -]; - -MessageDisplay[cells_] := Block[{msgCells}, - If[CurrentValue[{StyleDefinitions, ""}] == {}, Return[]]; - SelectionMove[First @ Cells[CellTags -> "$monitor"], After, Cell, AutoScroll -> False]; - NotebookWrite[EvaluationNotebook[], cells]; - NotebookLocate["$title"]; -]; - -CleanMessages[maxCount_] := With[{msgCells = Cells[CellTags -> "$msg"]}, - If[Length @ msgCells > maxCount, NotebookDelete[Drop[msgCells, maxCount]]]; -]; - -RawDisplay[text_] := FormBox[StyleBox["\"" <> text <> "\"", FontFamily -> "Calibri"], "InputForm"]; - - MenuCell = Cell[BoxData @ RowBox[{(* TemplateBox[{4}, "Spacer1"], TemplateBox[{ diff --git a/library/Assets/Develop.wl b/library/Interface/Develop.wl similarity index 61% rename from library/Assets/Develop.wl rename to library/Interface/Develop.wl index 5b3c0ea..d5a646d 100644 --- a/library/Assets/Develop.wl +++ b/library/Interface/Develop.wl @@ -1,17 +1,6 @@ (* ::Package:: *) -BeginPackage["Thulium`Interface`Develop`", { - "Thulium`System`", - "Thulium`Assets`" -}]; - -ModifySong::usage = "ModifySong"; -DeleteSong::usage = "DeleteSong"; -AddSong::usage = "AddSong"; - -Begin["`Private`"]; - -ModifySong[song_] := Module[{textInfo}, +Thulium`ModifySong[song_] := Module[{textInfo}, textInfo=SongIndex[[song,textInfoTags]]; CreateDialog[Column[{Spacer[{20,20}], Caption[textInfo[["SongName"]],"Title"], @@ -25,7 +14,7 @@ ModifySong[song_] := Module[{textInfo}, Grid[{ {Button[TextDict[["Save"]],putTextInfo[song,textInfo],ImageSize->150,Enabled->Dynamic[textInfo["SongName"]!=""]], Button[TextDict[["Undo"]],textInfo=SongIndex[[song,textInfoTags]],ImageSize->150]}, - {Button[TextDict[["DeleteSong"]],DialogReturn[DeleteSong[song]],ImageSize->150], + {Button[TextDict[["DeleteSong"]],DialogReturn[Thulium`DeleteSong[song]],ImageSize->150], Button[TextDict[["Return"]],DialogReturn[Thulium`Playlist["All"]],ImageSize->150]} }],Spacer[{20,20}] },Center,ItemSize->Full,Spacings->1], @@ -49,33 +38,45 @@ addSong[songPath_,textInfo_]:=Module[{song,metaInfo,audio}, putTextInfo[song,textInfo]; ]; -ignoreList={"test.qys"}; -AddSong[]:=Module[{songPath,textInfo,candidates}, - textInfo=AssociationMap[""&,textInfoTags]; +ignoreList = {"test.tm"}; +Thulium`AddSong[] := Block[{candidates, textInfo}, SetDirectory[$LocalPath]; - candidates=Complement[StringDrop[StringReplace["\\"->"/"]/@FileNames["*.tm","Songs",Infinity],6], - #<>".tm"&/@Keys@SongIndex, + candidates = Complement[ + StringDrop[ + StringReplace["\\" -> "/"] /@ FileNames["*.tm", "Songs", Infinity], + 6], + # <> ".tm"& /@ Keys @ SongIndex, ignoreList ]; + If[Length @ candidates === 0, Return[Thulium`Playlist["All"]]]; + DynamicModule[{songPath, textInfo = AssociationMap[""&, textInfoTags]}, CreateDialog[Column[{Spacer[{40,40}], Caption[TextDict["AddSong"],"Title"], Spacer[4], - Row[{TextDict[["SongPath"]],Spacer[12],PopupMenu[Dynamic@songPath,candidates,ImageSize->200]}], + Row[{ + TextDict[["SongPath"]], + Spacer[12], + PopupMenu[Dynamic @ songPath, candidates, ImageSize->200] + }], Column[Row[{Spacer[40], Caption[TagName[[#]],"Text"], Spacer[16], - InputField[Dynamic@textInfo[[#]],String], + InputField[Dynamic @ textInfo[[#]], String], Spacer[40]}]&/@textInfoTags], Spacer[4], - Row[{Button[TextDict[["Add"]],addSong[songPath,textInfo];DialogReturn[Thulium`Homepage[]], - ImageSize->150,Enabled->Dynamic[textInfo[["SongName"]]!=""]], - Spacer[20], - Button[TextDict[["Return"]],DialogReturn[uiPlaylist["All"]],ImageSize->150]}], + Row[{ + Button[TextDict[["Add"]], + addSong[songPath, textInfo]; + DialogReturn[Thulium`Homepage[]], + ImageSize -> 150, Enabled -> Dynamic[textInfo[["SongName"]] =!= ""]], + Spacer[20], + Button[TextDict[["Return"]],DialogReturn[Thulium`Playlist["All"]],ImageSize->150] + }], Spacer[{40,40}]},Center,ItemSize->Full,Spacings->1], - Background->WindowBackground,WindowTitle->TextDict["AddSong"]] + Background->WindowBackground,WindowTitle->TextDict["AddSong"]]] ]; -DeleteSong[song_]:=CreateDialog[Column[{"", +Thulium`DeleteSong[song_]:=CreateDialog[Column[{"", TextDict[["SureToRemove"]],"", Row[{ Button[TextDict[["Confirm"]], @@ -84,23 +85,15 @@ DeleteSong[song_]:=CreateDialog[Column[{"", DialogReturn[Thulium`Playlist["All"]], ImageSize->100], Spacer[20], - Button[TextDict[["Return"]],DialogReturn[ModifySong[song]],ImageSize->100] + Button[TextDict[["Return"]],DialogReturn[Thulium`ModifySong[song]],ImageSize->100] }],"" },Center,ItemSize->36], Background->WindowBackground,WindowTitle->TextDict["DeleteSong"]]; -End[]; - -EndPackage[]; - -Thulium`ModifySong = Thulium`Interface`Develop`ModifySong; -Thulium`AddSong = Thulium`Interface`Develop`AddSong; -Thulium`DeleteDong = Thulium`Interface`Develop`DeleteSong; - (* ::Input:: *) (*ModifySong["Anima"];*) (* ::Input:: *) -(*AddSong;*) +(*AddSong[];*) diff --git a/library/Assets/Homepage.wl b/library/Interface/Homepage.wl similarity index 94% rename from library/Assets/Homepage.wl rename to library/Interface/Homepage.wl index 1194a38..722fad4 100644 --- a/library/Assets/Homepage.wl +++ b/library/Interface/Homepage.wl @@ -86,12 +86,12 @@ Thulium`Playlist[playlist_] := Block[{info, songList, songListPaged, pageCount}, SmartButton["Play", DialogReturn[PageIndex[[playlist]] = page; Thulium`Player[song]]], Spacer[10], If[UserInfo["Developer"] && playlist == "All", Row[{ - SmartButton["Modify", DialogReturn[PageIndex[[playlist]] = page; Thulium`ModifySong[song]]], + SmartButton["Modify", "ModifySong", DialogReturn[PageIndex[[playlist]] = page; Thulium`ModifySong[song]]], Spacer[10], - SmartButton["Add", DialogReturn[PageIndex[[playlist]] = page; Thulium`AddSong[]]], + SmartButton["Add", "AddSong", DialogReturn[PageIndex[[playlist]] = page; Thulium`AddSong[]]], Spacer[10]}], Nothing], - SmartButton["ArrowL", DialogReturn[PageIndex[[playlist]] = page; Thulium`Homepage[]]], + SmartButton["Return", DialogReturn[PageIndex[[playlist]] = page; Thulium`Homepage[]]], Spacer[40] }, Alignment -> Right, ImageSize -> {480, 56}] }], diff --git a/library/Interface/Login.wl b/library/Interface/Login.wl new file mode 100644 index 0000000..905c9f5 --- /dev/null +++ b/library/Interface/Login.wl @@ -0,0 +1,110 @@ +(* ::Package:: *) + +BeginPackage["Thulium`Interface`Login`", { + "Thulium`System`", + "Thulium`Assets`" +}]; + +Login::usage = "Login"; + +Begin["`Private`"]; + +SetAttributes[tmInputField, HoldRest]; +Options[tmInputField] = { + FieldHint -> "", + FieldMasked -> False +}; +tmInputField[symbol_, test_, OptionsPattern[]] := FrameBox[ + InputFieldBox[Dynamic[symbol], String, + FieldHint -> OptionValue[FieldHint], + FieldMasked -> OptionValue[FieldMasked] + ], + FrameStyle -> Dynamic @ If[test, RGBColor[0.6, 1, 0.8], RGBColor[1, 0.7, 0.7], RGBColor[1, 0.7, 0.7]], + Background -> Dynamic @ If[test, RGBColor[0.92, 1, 0.96], RGBColor[1, 0.94, 0.94], RGBColor[1, 0.94, 0.94]] +]; + +Login[] := Module[{username, password, remember}, + CreateDialog[ + { + Cell[BoxData @ StyleBox[TextDict["LoginTitle"], "Title"], "Title"], + Cell[BoxData @ GridBox[{ + { + TextDict["UserName"], + tmInputField[username, username != "", FieldHint -> TextDict["EnterUserName"]] + }, + { + TextDict["Password"], + tmInputField[password, password != "", FieldHint -> TextDict["EnterPassword"], FieldMasked -> True] + } + }, ColumnAlignments -> Center], "Form"], + TextCell[Dynamic[username]], + TextCell[Dynamic[IntegerString[Hash[password, "SHA256"], 16]]] + }, + + StyleDefinitions -> Notebook[{ + Cell[StyleData["Title"], + CellMargins -> {{8, 8}, {32, 32}}, + TextAlignment -> Center, + FontFamily -> ChsFont, + FontSize -> 32 + ], + + Cell[StyleData["Form"], + CellMargins -> {{4, 4}, {24, 24}}, + TextAlignment -> Center, + FrameBoxOptions -> { + RoundingRadius -> {4, 4}, + ImageMargins -> 0, + BoxFrame -> 1 + }, + InputFieldBoxOptions -> { + Background -> None, + Appearance -> "Frameless", + FieldSize -> {8, 1}, + ImageMargins -> {{4, 4}, {4, 0}}, + BaseStyle -> { + FontSize -> 20, + FontFamily -> EngFont, + FontSlant -> Plain, + FontColor -> RGBColor[0, 0, 0] + }, + FieldHintStyle -> { + FontSize -> 20, + FontFamily -> ChsFont, + FontSlant -> Plain, + FontColor -> GrayLevel[0.4] + } + } + ] + }], + + ShowCellLabel -> False, + ShowCellTags -> False, + ShowCellBracket -> False, + CellGrouping -> Manual, + Background -> RGBColor[1, 1, 1], + WindowTitle -> TextDict["Login"], + WindowElements -> {}, + WindowFrameElements -> {"CloseBox", "MinimizeBox"}, + WindowSize -> {800, 600}, + WindowFrame -> "ModelessDialog", + Magnification -> 2, + Saveable -> False, + Evaluatable -> False, + Editable -> False, + Deployed -> True, + DynamicEvaluationTimeout -> 30 + ]; +]; + +End[]; + +EndPackage[]; + + +(* ::Input:: *) +(*Thulium`Interface`Login`Login[];*) + + +(* ::Input:: *) +(*InputFieldBox//Options*) diff --git a/library/Assets/Others.wl b/library/Interface/Others.wl similarity index 91% rename from library/Assets/Others.wl rename to library/Interface/Others.wl index 9750977..543b42c 100644 --- a/library/Assets/Others.wl +++ b/library/Interface/Others.wl @@ -28,10 +28,10 @@ Settings[] := Module[{choices = UserInfo}, UserInfo=choices; Export[$UserPath<>"Default.json",UserInfo]; RefreshLanguage; - DialogReturn[Thulium`homepage], + DialogReturn[Thulium`Homepage[]], ImageSize->150], Spacer[10], - Button[TextDict["Return"],DialogReturn[Thulium`homepage],ImageSize->150] + Button[TextDict["Return"],DialogReturn[Thulium`Homepage[]],ImageSize->150] }],Spacer[{40,40}] },Center,ItemSize->Full], Background->WindowBackground,WindowTitle->TextDict["Settings"]] @@ -70,7 +70,7 @@ About[] := CreateDialog[Column[{Spacer[{40,40}], },Alignment->Left] },Alignment->Left,ItemSize->Full],Spacer[60]}], Spacer[{20,20}], - Button[TextDict["Return"],DialogReturn[Thulium`homepage],ImageSize->100], + Button[TextDict["Return"],DialogReturn[Thulium`Homepage[]],ImageSize->100], Spacer[{40,40}]},Center,ItemSize->Full], WindowTitle->TextDict["About"],Background->WindowBackground]; diff --git a/library/Interface/Player.wl b/library/Interface/Player.wl new file mode 100644 index 0000000..757a446 --- /dev/null +++ b/library/Interface/Player.wl @@ -0,0 +1,140 @@ +(* ::Package:: *) + +BeginPackage["Thulium`Interface`Player`", { + "Thulium`System`", + "Thulium`Assets`", + "Thulium`Graphics`", + "Thulium`SmartButton`" +}]; + +Player::usage = "Thulium Music Player Interface"; + +Begin["`Private`"]; + +PlayerControls[audio_] := Module[ + { + stream = AudioPlay[audio], time, + duration = QuantityMagnitude[Duration[audio], "Seconds"] + }, + time := QuantityMagnitude[stream["Position"], "Seconds"]; + With[{StatusAlias = StatusAlias}, Column[{ + Row[{ + Column[{Style[Dynamic[TimeDisplay[time]], 20], Spacer[1]}], + Spacer[7], + Magnify[EventHandler[ + Dynamic[Graphics[{progressSlider[time / duration, 16]}]], + {"MouseDragged" :> (stream["Position"] = duration * progressLocate[16])} + ], 3.6], + Spacer[8], + Column[{Style[TimeDisplay[duration], 20], Spacer[1]}] + }, ImageSize -> Full, Alignment -> Center], + Row[Riffle[{ + If[$VersionNumber >= 11.3, + Dynamic @ SwitchButton[stream["AudioLooping"], + {False, "Loop", Hold[stream["AudioLooping"] = True]}, + {True, "Single", Hold[stream["AudioLooping"] = False]} + ], + Nothing + ], + Dynamic @ SwitchButton[stream[StatusAlias], + {"Playing", "Pause", Hold[stream[StatusAlias] = "Paused"]}, + {"Paused", "Play", Hold[stream[StatusAlias] = "Playing"]}, + {"Stopped", "Play", Hold[stream[StatusAlias] = "Playing"]} + ], + SmartButton["Stop", stream[StatusAlias] = "Stopped"; stream["Position"] = 0], + SmartButton["Return", AudioStop[]; DialogReturn[Thulium`Playlist[Thulium`CurrentPlaylist]]] + }, Spacer[20]], ImageSize -> {Automatic, 60}, Alignment -> Center] + }, Alignment -> Center] +]]; + +ImageDisplay[image_] := Block[ + {source, aspectRatio}, + source = Import[$DataPath <> "Images/" <> image]; + aspectRatio = ImageAspectRatio[source]; + Row[{ + Spacer[48], + Column[{ + Spacer[{40, 40}], + TooltipDisplay[ + ImageEffect[Image[source, ImageSize -> Piecewise[{ + {{Automatic, 600}, aspectRatio > 2}, + {{480, Automatic}, aspectRatio < 1/2}, + {{Automatic, 400}, aspectRatio <= 1 && aspectRatio > 1/2}, + {{360, Automatic}, aspectRatio > 1 && aspectRatio < 2} + }]], {"FadedFrame"}], + If[ImageIndex[image] != <||>, + Grid[ + If[KeyExistsQ[ImageIndex[image], #], + {TagName[[#]] <> ":", ImageIndex[image, #]}, + Nothing + ]& /@ imageTags, + Spacings -> 0.4, + Alignment -> {{Center, Left}} + ], + TextDict["NoImageInfo"], + TextDict["NoImageInfo"] + ] + ], + Spacer[{40, 40}] + }] + }] +]; + +Player[song_] := Block[{image, audio, imageExist = False, aspectRatio}, + Quiet @ Check[ + audio = Import[$DataPath <> "Buffer/" <> song <> ".buffer", "MP3"], + Return[Thulium`Playlist[Thulium`CurrentPlaylist]], + Import::nffil]; + AudioStop[]; + CreateDialog[Row[{ + If[SongIndex[song, "Image"] != "", + ImageDisplay[SongIndex[song, "Image"]], + Nothing + ], + Spacer[48], + Column[{ + Spacer[{60, 60}], + If[SongIndex[song, "Comment"] != "", + If[TextLength @ SongIndex[song, "Comment"] > 16, Column, Row][{ + Caption[SongIndex[song, "SongName"], "Title"], + Caption[" (" <> SongIndex[song, "Comment"] <> ")", "TitleCmt"] + }, Alignment -> Center], + Caption[SongIndex[song, "SongName"], "Title"] + ], + Spacer[1], + Column[If[SongIndex[song, #] != "", + Caption[TagName[[#]] <> ": " <> SongIndex[[song, #]], "Text"], + Nothing + ]& /@ {"Origin", "Composer", "Lyricist", "Adapter"}, Alignment -> Center], + Spacer[1], + If[SongIndex[song, "Abstract"] != "", + Column[Caption[#, "Text"]& /@ StringSplit[SongIndex[song, "Abstract"], "\n"], Center], + Nothing + ], + Spacer[1], + PlayerControls[audio], + Spacer[{60, 60}] + }, Alignment -> Center, ItemSize -> Full], + Spacer[48] + }, Alignment -> Center,ImageSize -> Full], + Background -> WindowBackground, + WindowTitle -> TextDict["Playing"] <> ": " <> SongIndex[song, "SongName"]]; +]; + +End[]; + +EndPackage[]; + +Thulium`Player = Thulium`Interface`Player`Player; + + +(* ::Input:: *) +(*Thulium`Playlist["All"];*) + + +(* ::Input:: *) +(*AudioStop[];*) + + +(* ::Input:: *) +(*Thulium`Player["Touhou/Dream_Battle"]*) diff --git a/library/Assets/StyleSheet/Core.style.wl b/library/Interface/StyleSheet/Core.style.wl similarity index 100% rename from library/Assets/StyleSheet/Core.style.wl rename to library/Interface/StyleSheet/Core.style.wl diff --git a/library/Assets/StyleSheet/Document.style.wl b/library/Interface/StyleSheet/Document.style.wl similarity index 100% rename from library/Assets/StyleSheet/Document.style.wl rename to library/Interface/StyleSheet/Document.style.wl diff --git a/library/Assets/Update.wl b/library/Interface/Update.wl similarity index 95% rename from library/Assets/Update.wl rename to library/Interface/Update.wl index 0daab3c..806b95a 100644 --- a/library/Assets/Update.wl +++ b/library/Interface/Update.wl @@ -1,6 +1,10 @@ (* ::Package:: *) -BeginPackage["Thulium`Update`", {"Thulium`System`", "Thulium`Assets`"}]; +BeginPackage["Thulium`Update`", { + "Thulium`System`", + "Thulium`Assets`", + "Thulium`Graphics`" +}]; CheckUpdate::usage = "CheckUpdate"; @@ -42,7 +46,7 @@ CheckUpdate := Block[ SetDirectory[$DataPath]; bufferHash = Association @ Import[$DataPath <> "Buffer.json"]; bufferList = StringReplace["\\" -> "/"] /@ StringTake[FileNames["*.buffer", "Buffer", Infinity], {8, -8}]; - Scan[DeleteFile[# <> ".buffer"]&, Complement[ToLowerCase /@ bufferList, ToLowerCase /@ songList]]; + Scan[DeleteFile[$DataPath <> "buffer/" <> # <> ".buffer"]&, Complement[ToLowerCase /@ bufferList, ToLowerCase /@ songList]]; imageList = DeleteCases[Values @ SongIndex[[All, "Image"]], ""]; imageDirList = DeleteDuplicates[DirectoryName /@ imageList]; Scan[If[!DirectoryQ[#], CreateDirectory[#]]&["images/" <> #]&, imageDirList]; @@ -128,7 +132,7 @@ CheckUpdate := Block[ filename = newImages[[i]]; metaFileName = StringReplace[filename, RegularExpression["\\.[^\\.]+$"] -> ".json"]; image = Import[$CloudPath <> "images/" <> filename]; - Export[$DataPath <> "Images/" <> filename, image]; + If[!FailureQ[image], Export[$DataPath <> "Images/" <> filename, image]]; AssociateTo[ImageIndex, filename -> Association @ Import[$CloudPath <> "images/" <> metaFileName]] ], {i, Length @ newImages}], ProgressDisplay[newImages, i, "Downloading images from the internet ......"]]]; diff --git a/library/Assets/WorkBench.wl b/library/Interface/WorkBench.wl similarity index 100% rename from library/Assets/WorkBench.wl rename to library/Interface/WorkBench.wl diff --git a/library/Interface/newPlaylist.wl b/library/Interface/newPlaylist.wl new file mode 100644 index 0000000..56e25d0 --- /dev/null +++ b/library/Interface/newPlaylist.wl @@ -0,0 +1,75 @@ +(* ::Package:: *) + +BeginPackage["Thulium`Interface`Playlist`", { + "Thulium`System`", + "Thulium`Assets`" +}]; + +newPlaylist::usage = "newPlaylist"; + +Begin["`Private`"]; + +newPlaylist[playlist_] := Block[ + {info, length, songList, indexList, pageCount}, + info = PlaylistIndex[playlist]; + length = Length @ info["SongList"]; + pageCount = Ceiling[length / ListSize]; + songList = Partition["Song" /. info["SongList"], UpTo @ Ceiling[length / pageCount]]; + indexList = Partition["Index" /. info["SongList"], UpTo @ Ceiling[length / pageCount]]; + If[Thulium`PageIndex[playlist] > pageCount, Thulium`PageIndex[playlist] = pageCount]; + Module[{page = Thulium`PageIndex[playlist], index = 1}, + CreateDialog[ + { + Cell[BoxData @ GridBox[{ + {TemplateBox[{Unevaluated[index], 1, "booo", "booo"}, ""]}, + {TemplateBox[{Unevaluated[index], 2, "fooo", "fooo"}, ""]}, + {TemplateBox[{Unevaluated[index], 3, "wooo", "wooo"}, ""]} + }, RowSpacings -> 0]], + TextCell[Dynamic @ index] + }, + + StyleDefinitions -> Notebook[{ + Thulium`StyleSheet`Include["Setter-Item"], + Thulium`StyleSheet`Include["Setter"], + Thulium`StyleSheet`Include["Tooltip"], + + Cell[StyleData[""], + TemplateBoxOptions -> {DisplayFunction -> Function[ + TemplateBox[{ + #1, #2, #3, + TemplateBox[{#4, RGBColor[0, 0, 0], RGBColor[0.96, 0.98, 1], RGBColor[0.96, 0.98, 1], 200, 36}, ""], + TemplateBox[{#4, RGBColor[0, 0, 0], RGBColor[0.96, 1, 0.98], RGBColor[0.94, 1, 0.98], 200, 36}, ""], + TemplateBox[{#4, RGBColor[0, 0, 0], RGBColor[0.92, 1, 0.98], RGBColor[0.88, 1, 0.98], 200, 36}, ""], + TemplateBox[{#4, RGBColor[0, 0, 0], RGBColor[0.97, 1, 0.97], RGBColor[0.97, 1, 0.97], 200, 36}, ""] + }, ""] + ]} + ] + }], + + ShowCellLabel -> False, + ShowCellTags -> False, + ShowCellBracket -> False, + CellGrouping -> Manual, + Background -> RGBColor[1, 1, 1], + WindowTitle -> TagName[info["Type"]] <> " - " <> info["Title"], + WindowElements -> {}, + WindowFrameElements -> {"CloseBox", "MinimizeBox"}, + WindowSize -> {800, 600}, + WindowFrame -> "ModelessDialog", + Magnification -> 2, + Saveable -> False, + Evaluatable -> False, + Editable -> False, + Deployed -> True, + DynamicEvaluationTimeout -> 30 + ]; + ]; +]; + +End[]; + +EndPackage[]; + + +(* ::Input:: *) +(*newPlaylist["All"];*) diff --git a/library/Package/.Graphics.mx b/library/Package/.Graphics.mx index b5003f5..034b7b5 100644 Binary files a/library/Package/.Graphics.mx and b/library/Package/.Graphics.mx differ diff --git a/library/Package/Assets.mx b/library/Package/Assets.mx index 0906c95..b392b47 100644 Binary files a/library/Package/Assets.mx and b/library/Package/Assets.mx differ diff --git a/library/Package/PageSelector.mx b/library/Package/PageSelector.mx index e041d70..d4da83f 100644 Binary files a/library/Package/PageSelector.mx and b/library/Package/PageSelector.mx differ diff --git a/library/Package/SmartButton.mx b/library/Package/SmartButton.mx index 3052c21..412d79c 100644 Binary files a/library/Package/SmartButton.mx and b/library/Package/SmartButton.mx differ diff --git a/library/Package/StyleSheet.mx b/library/Package/StyleSheet.mx index 22aa98f..235cbd5 100644 Binary files a/library/Package/StyleSheet.mx and b/library/Package/StyleSheet.mx differ diff --git a/library/Parser b/library/Parser index ecdf98f..0fd8f76 160000 --- a/library/Parser +++ b/library/Parser @@ -1 +1 @@ -Subproject commit ecdf98f4a9c501eb6fc8fa35bea04fc263bc3ed7 +Subproject commit 0fd8f76d08f093d63ed6471317eeb5407a1c0a1e diff --git a/library/Preload.wl b/library/Preload.wl index dc2478a..32bec10 100644 --- a/library/Preload.wl +++ b/library/Preload.wl @@ -4,7 +4,7 @@ Begin["Thulium`System`"]; Begin["`Private`"]; -$$Version = "2.3"; +$$Version = "2.4"; $$Build = 701; If[DirectoryQ[$LocalPath <> ".git"], With[{ref = StringCases[Import[$LocalPath <> ".git/HEAD"], RegularExpression["^ref: (.+)$"] :> "$1"][[1]]}, @@ -43,7 +43,12 @@ uiSetPath := Module[{path = defaultDataPath}, Spacer[96], Column[{ Spacer[{48,48}], - Graphics[{logo},ImageSize->{512,Automatic}], + Graphics[{ + RGBColor["#00A0E9"], + FilledCurve[{BezierCurve[Thulium`Assets`LogoCloud]}], + RGBColor["#FFFFFF"], + FilledCurve[{BezierCurve[Thulium`Assets`LogoNote]}] + },ImageSize->{512,Automatic}], Spacer[1], Caption[TextDict["ChooseBasePath"],"Title"], Row[{ diff --git a/library/Token b/library/Token index f078440..071b5db 160000 --- a/library/Token +++ b/library/Token @@ -1 +1 @@ -Subproject commit f078440257ab98a84e50379cf9528ae0a93193d8 +Subproject commit 071b5db9ea55aad6408146394a2d61613af61f72 diff --git a/package/Ammonia/main.tml b/package/Ammonia/main.tml index 98a696c..0b2f16e 100644 --- a/package/Ammonia/main.tml +++ b/package/Ammonia/main.tml @@ -22,94 +22,96 @@ j 2nd inversion [2:], [:1]+12 # Function function Con(octave, scale = 1) { - if (octave === 0) { - for (const name in this.Library.Pitch) { - if (this.Library.Pitch[name].Generated) { - this.Library.Pitch[name].splice(1) - } - } - } else { - for (const name in this.Library.Pitch) { - if (this.Library.Pitch[name].Generated && '1' <= name && name <= '9') { - const source = this.Library.Pitch[name][0] - this.Library.Pitch[name].splice(1) - this.Library.Pitch[name].push({ - Pitch: source.Pitch + octave * 12, - Volume: scale - }) - } - } - } + if (octave === 0) { + for (const name in this.Library.Pitch) { + if (this.Library.Pitch[name].Generated) { + this.Library.Pitch[name].splice(1) + } + } + } else { + for (const name in this.Library.Pitch) { + if (this.Library.Pitch[name].Generated && '1' <= name && name <= '9') { + const source = this.Library.Pitch[name][0] + this.Library.Pitch[name].splice(1) + this.Library.Pitch[name].push({ + Pitch: source.Pitch + octave * 12, + Volume: scale + }) + } + } + } } function Vol(volume) { - // alias: (${0:uns}%) - this.Settings.assignSetting('Volume', volume / 100, (volume) => volume > 0) + // alias: (${0:uns}%) + this.Settings.assignSetting('Volume', volume / 100, (volume) => volume > 0) } function Key(key) { - // alias: (1=${0:str}) - if (typeof key === 'string') { - const match = arguments[0].match(/^((#|b)\2*)?([A-G])(('|,)\5*)?/) - this.Settings.Key = { C: 0, G: 7, D: 2, A: 9, E: 4, B: -1, F: 5 }[match[3]] - this.Settings.Key += (!match[2]) ? 0 : (match[2] === 'b' ? -1 : 1) * match[1].length - this.Settings.Key += (!match[5]) ? 0 : (match[5] === ',' ? -12 : 12) * match[4].length - } else { - this.Settings.Key = key - } + // alias: (1=${0:str}) + if (typeof key === 'string') { + const match = arguments[0].match(/^((#|b)\2*)?([A-G])(('|,)\5*)?/) + this.Settings.Key = { C: 0, G: 7, D: 2, A: 9, E: 4, B: -1, F: 5 }[match[3]] + this.Settings.Key += (!match[2]) ? 0 : (match[2] === 'b' ? -1 : 1) * match[1].length + this.Settings.Key += (!match[5]) ? 0 : (match[5] === ',' ? -12 : 12) * match[4].length + } else { + this.Settings.Key = key + } } function KeyShift(delta) { - // alias: (${0:sig}) - this.Settings.Key += delta + // alias: (${0:sig}) + this.Settings.Key += delta } function Oct(octave) { - const tonality = (this.Settings.Key + 2) % 12 - this.Settings.Key = tonality - 2 + octave * 12 + const tonality = this.Settings.Key >= -2 + ? (this.Settings.Key + 2) % 12 + : (this.Settings.Key + 2) % 12 + 12 + this.Settings.Key = tonality - 2 + octave * 12 } function Spd(speed) { - // alias: (${0:uns}) - this.Settings.assignSetting('Speed', speed, (speed) => speed > 0); + // alias: (${0:uns}) + this.Settings.assignSetting('Speed', speed, (speed) => speed > 0); } function BarBeat(bar, beat) { - // alias: (${0:uns}/${1:uns}) - this.Settings.assignSetting('Bar', bar, (bar) => bar > 0 && Number.isInteger(bar)) - this.Settings.assignSetting('Beat', beat, (beat) => beat > 0 && Number.isInteger(Math.log2(beat))) + // alias: (${0:uns}/${1:uns}) + this.Settings.assignSetting('Bar', bar, (bar) => bar > 0 && Number.isInteger(bar)) + this.Settings.assignSetting('Beat', beat, (beat) => beat > 0 && Number.isInteger(Math.log2(beat))) } function Dur(scale) { - this.Settings.assignSetting('Duration', scale, () => true) + this.Settings.assignSetting('Duration', scale, () => true) } function Acct(scale) { - this.Settings.assignSetting('Accent', scale, (scale) => scale > 1) + this.Settings.assignSetting('Accent', scale, (scale) => scale > 1) } function Light(scale) { - this.Settings.assignSetting('Light', scale, (scale) => scale < 1 && scale > 0) + this.Settings.assignSetting('Light', scale, (scale) => scale < 1 && scale > 0) } function Trace(count) { - this.Settings.assignSetting('Trace', count, (count) => count > 0 && count <= 4 && Number.isInteger(count)) + this.Settings.assignSetting('Trace', count, (count) => count > 0 && count <= 4 && Number.isInteger(count)) } function FadeIn(time) { - this.Settings.assignSetting('FadeIn', time, (time) => time >= 0) + this.Settings.assignSetting('FadeIn', time, (time) => time >= 0) } function FadeOut(time) { - this.Settings.assignSetting('FadeOut', time, (time) => time >= 0) + this.Settings.assignSetting('FadeOut', time, (time) => time >= 0) } function Rev(r) { - this.Settings.assignSetting('Rev', r, () => true) + this.Settings.assignSetting('Rev', r, () => true) } function Stac(rest, index = 1) { - this.Settings.assignSettingAtIndex('Stac', index, rest, (rest) => rest >= 0 && rest <= 1) + this.Settings.assignSettingAtIndex('Stac', index, rest, (rest) => rest >= 0 && rest <= 1) } # End