Lay out the song list's pictures and text to fit any number of players
The players' pictures sit on the right in even lines of at most four, each ending at the row's right edge, so five pictures are 3 + 2 and seven 4 + 3. The text takes the room they leave and wraps only when it does not fit, and the row is as tall as the taller of the two, instead of a width fixed by the number of pictures. Rows are rounded and alternate like the other lists, are highlighted under the mouse, and the playing song has an orange edge. Clicking a picture clicks its song.
This commit is contained in:
1 parent
84e137e16a
commit
78e1facaf0
10 files changed
+753
-361
No files matched your search
+224
-296
@@ -1001,66 +1001,57 @@
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
384.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
384.0,
|
||||
78.0,
|
||||
394.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicPlayer": {
|
||||
"rect": [
|
||||
@@ -4603,111 +4594,93 @@
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
430.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
434.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
422.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
434.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
422.0,
|
||||
78.0,
|
||||
434.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
384.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
384.0,
|
||||
78.0,
|
||||
394.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicPlayer": {
|
||||
"rect": [
|
||||
@@ -11454,66 +11427,57 @@
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
384.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
384.0,
|
||||
78.0,
|
||||
394.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicPlayer": {
|
||||
"rect": [
|
||||
@@ -15398,127 +15362,118 @@
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
430.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
434.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
422.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
434.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
422.0,
|
||||
78.0,
|
||||
434.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
968.0,
|
||||
384.0,
|
||||
75.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
900.0,
|
||||
78.0,
|
||||
394.0,
|
||||
932.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1047.0,
|
||||
384.0,
|
||||
105.0,
|
||||
25.0
|
||||
1022.0,
|
||||
394.0,
|
||||
116.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#0": {
|
||||
"rect": [
|
||||
1047.0,
|
||||
384.0,
|
||||
51.0,
|
||||
25.0
|
||||
1022.0,
|
||||
394.0,
|
||||
116.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#1": {
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#0/#0": {
|
||||
"rect": [
|
||||
1102.0,
|
||||
384.0,
|
||||
50.0,
|
||||
25.0
|
||||
1022.0,
|
||||
394.0,
|
||||
56.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#0/#1": {
|
||||
"rect": [
|
||||
1082.0,
|
||||
394.0,
|
||||
56.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
@@ -23530,66 +23485,57 @@
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
384.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
384.0,
|
||||
78.0,
|
||||
394.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicPlayer": {
|
||||
"rect": [
|
||||
@@ -36583,127 +36529,118 @@
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
430.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
434.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
422.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
422.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
434.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/#1/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
422.0,
|
||||
78.0,
|
||||
434.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
968.0,
|
||||
384.0,
|
||||
75.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
900.0,
|
||||
78.0,
|
||||
394.0,
|
||||
932.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1047.0,
|
||||
384.0,
|
||||
105.0,
|
||||
25.0
|
||||
1022.0,
|
||||
394.0,
|
||||
116.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#0": {
|
||||
"rect": [
|
||||
1047.0,
|
||||
384.0,
|
||||
51.0,
|
||||
25.0
|
||||
1022.0,
|
||||
394.0,
|
||||
116.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#1": {
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#0/#0": {
|
||||
"rect": [
|
||||
1102.0,
|
||||
384.0,
|
||||
50.0,
|
||||
25.0
|
||||
1022.0,
|
||||
394.0,
|
||||
56.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers/#0/#1": {
|
||||
"rect": [
|
||||
1082.0,
|
||||
394.0,
|
||||
56.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
@@ -41251,66 +41188,57 @@
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
512.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
500.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
28.0
|
||||
70.0,
|
||||
390.0,
|
||||
1076.0,
|
||||
36.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1088.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/Panel": {
|
||||
"rect": [
|
||||
1068.0,
|
||||
384.0,
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListLabel": {
|
||||
"rect": [
|
||||
64.0,
|
||||
384.0,
|
||||
1000.0,
|
||||
78.0,
|
||||
394.0,
|
||||
1060.0,
|
||||
28.0
|
||||
],
|
||||
"visible": true
|
||||
},
|
||||
"Quiz/MusicListPanel/ScrollContainer/MusicList/SongRow/HBoxContainer/SongListPlayers": {
|
||||
"rect": [
|
||||
1152.0,
|
||||
384.0,
|
||||
78.0,
|
||||
394.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"visible": true
|
||||
"visible": false
|
||||
},
|
||||
"Quiz/MusicPlayer": {
|
||||
"rect": [
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
extends GdUnitTestSuite
|
||||
## How a song in the music list is laid out: the players' pictures on the right in even
|
||||
## lines of at most four, each ending at the row's right edge, the text in the room they leave, wrapping only when it does
|
||||
## not fit, and the row as tall as the taller of the two. Checked for every number of
|
||||
## players, with short, debug mode and very long song texts.
|
||||
|
||||
const SHORT: Array[String] = ["Chrono Trigger", "Corridors of Time"]
|
||||
const LONG: Array[String] = [
|
||||
"Final Fantasy Dissidia 012 Duodecim (Sista Fantasin Meningsskiljaktigheter 012 Tolv)",
|
||||
"'Crystal Cave -arrange-' from FINAL FANTASY III",
|
||||
]
|
||||
## The row's padding, from the SongRow styles in the theme.
|
||||
const PADDING: float = 8.0
|
||||
|
||||
var _snapshot: AutoloadSnapshot
|
||||
var _runner: GdUnitSceneRunner
|
||||
var _panel: MusicListPanel
|
||||
# The panel's width in the quiz, which songs must never make wider
|
||||
var _panel_width: float
|
||||
|
||||
|
||||
func before_test() -> void:
|
||||
_snapshot = AutoloadSnapshot.take([Settings, Playlist])
|
||||
Settings.is_debug = false
|
||||
Playlist.reset_playlist()
|
||||
Settings.player_array.clear()
|
||||
for i: int in Settings.MAX_NUMBER_OF_PLAYERS:
|
||||
Settings.player_array.append(PlayerObject.new("Player %d" % (i + 1)))
|
||||
_runner = scene_runner("res://quiz/MusicListPanel.tscn")
|
||||
_panel = _runner.scene()
|
||||
_panel_width = _panel.size.x
|
||||
|
||||
|
||||
func after_test() -> void:
|
||||
await await_idle_frame()
|
||||
_snapshot.restore()
|
||||
|
||||
|
||||
# Adds a played and answered song with points for the first [param players] players
|
||||
func _add_song(title: Array[String], players: int) -> SongObject:
|
||||
var song: SongObject = SongObject.new()
|
||||
song.song_number = Playlist.song_object_array.size()
|
||||
song.soundtrack_title = title[0]
|
||||
song.song_title = title[1]
|
||||
song.has_played = true
|
||||
song.is_answered = true
|
||||
for i: int in players:
|
||||
song.add_point(Settings.player_array[i].id)
|
||||
Playlist.add_to_playlist(song)
|
||||
return song
|
||||
|
||||
|
||||
func _show() -> void:
|
||||
_panel.refresh()
|
||||
await _runner.simulate_frames(3)
|
||||
|
||||
|
||||
func _rows() -> Array[SongRow]:
|
||||
var rows: Array[SongRow] = []
|
||||
rows.assign(_panel.get_node("%MusicList").get_children())
|
||||
return rows
|
||||
|
||||
|
||||
func _pictures(row: SongRow) -> Array[TextureRect]:
|
||||
return row.pictures()
|
||||
|
||||
|
||||
# How wide the row's text would be on one line
|
||||
func _text_width(row: SongRow) -> float:
|
||||
var label: Label = row.song_list_label
|
||||
return label.get_theme_font(&"font").get_string_size(label.text, HORIZONTAL_ALIGNMENT_LEFT,
|
||||
-1, label.get_theme_font_size(&"font_size")).x
|
||||
|
||||
|
||||
func _one_line_height() -> float:
|
||||
_add_song(SHORT, 0)
|
||||
await _show()
|
||||
var height: float = _rows()[0].size.y
|
||||
Playlist.reset_playlist()
|
||||
return height
|
||||
|
||||
|
||||
# Every number of players with every kind of text, in normal and debug mode
|
||||
func _each_layout(check: Callable) -> void:
|
||||
for debug: bool in [false, true]:
|
||||
Settings.is_debug = debug
|
||||
for title: Array[String] in [SHORT, LONG]:
|
||||
Playlist.reset_playlist()
|
||||
for players: int in Settings.MAX_NUMBER_OF_PLAYERS + 1:
|
||||
_add_song(title, players)
|
||||
await _show()
|
||||
assert_float(_panel.size.x).override_failure_message(
|
||||
"The songs made the list wider than its place in the quiz") \
|
||||
.is_equal(_panel_width)
|
||||
for row: SongRow in _rows():
|
||||
check.call(row, "%d players, %s text%s" % [_pictures(row).size(),
|
||||
"long" if title == LONG else "short", " (debug)" if debug else ""])
|
||||
|
||||
|
||||
# Columns
|
||||
|
||||
func test_pictures_are_spread_evenly_over_as_few_lines_as_possible() -> void:
|
||||
var columns: Array[int] = []
|
||||
for pictures: int in range(0, 9):
|
||||
columns.append(SongRow.picture_columns(pictures))
|
||||
|
||||
# 5 pictures are 3 + 2, not 4 + 1; 7 are 4 + 3
|
||||
assert_array(columns).contains_exactly([1, 1, 2, 3, 4, 3, 3, 4, 4])
|
||||
|
||||
|
||||
# Placement
|
||||
|
||||
func test_pictures_are_at_the_right_end_of_the_row() -> void:
|
||||
await _each_layout(func(row: SongRow, layout: String) -> void:
|
||||
if _pictures(row).is_empty():
|
||||
assert_bool(row.song_list_players.visible).override_failure_message(layout).is_false()
|
||||
return
|
||||
var pictures: Rect2 = row.song_list_players.get_global_rect()
|
||||
assert_float(pictures.end.x).override_failure_message(layout) \
|
||||
.is_equal_approx(row.get_global_rect().end.x - PADDING, 1.0))
|
||||
|
||||
|
||||
func test_every_line_of_pictures_ends_at_the_right_edge() -> void:
|
||||
await _each_layout(func(row: SongRow, layout: String) -> void:
|
||||
var right_edge: float = row.get_global_rect().end.x - PADDING
|
||||
for line: HBoxContainer in row.song_list_players.get_children():
|
||||
var last: TextureRect = line.get_child(line.get_child_count() - 1)
|
||||
assert_float(last.get_global_rect().end.x).override_failure_message(layout) \
|
||||
.is_equal_approx(right_edge, 1.0))
|
||||
|
||||
|
||||
func test_text_and_pictures_never_overlap_and_stay_inside_the_row() -> void:
|
||||
await _each_layout(func(row: SongRow, layout: String) -> void:
|
||||
var row_rect: Rect2 = row.get_global_rect().grow(0.5)
|
||||
var text: Rect2 = row.song_list_label.get_global_rect()
|
||||
assert_bool(row_rect.encloses(text)).override_failure_message(
|
||||
"Text outside the row: " + layout).is_true()
|
||||
for picture: TextureRect in _pictures(row):
|
||||
var rect: Rect2 = picture.get_global_rect()
|
||||
assert_bool(row_rect.encloses(rect)).override_failure_message(
|
||||
"Picture outside the row: " + layout).is_true()
|
||||
assert_float(rect.position.x).override_failure_message(
|
||||
"Picture over the text: " + layout).is_greater_equal(text.end.x))
|
||||
|
||||
|
||||
func test_text_gets_all_the_room_the_pictures_leave() -> void:
|
||||
await _each_layout(func(row: SongRow, layout: String) -> void:
|
||||
var text: Rect2 = row.song_list_label.get_global_rect()
|
||||
assert_float(text.position.x).override_failure_message(layout) \
|
||||
.is_equal_approx(row.get_global_rect().position.x + PADDING, 1.0)
|
||||
var right_end: float = row.get_global_rect().end.x - PADDING
|
||||
if row.song_list_players.visible:
|
||||
right_end = row.song_list_players.get_global_rect().position.x \
|
||||
- row.get_node("HBoxContainer").get_theme_constant(&"separation")
|
||||
assert_float(text.end.x).override_failure_message(layout) \
|
||||
.is_equal_approx(right_end, 1.0))
|
||||
|
||||
|
||||
func test_text_wraps_only_when_it_does_not_fit_on_one_line() -> void:
|
||||
await _each_layout(func(row: SongRow, layout: String) -> void:
|
||||
var lines: int = row.song_list_label.get_line_count()
|
||||
var room: float = row.song_list_label.size.x
|
||||
if _text_width(row) <= room - 1:
|
||||
assert_int(lines).override_failure_message("Wrapped though it fits: " + layout) \
|
||||
.is_equal(1)
|
||||
elif _text_width(row) > room + 1:
|
||||
assert_int(lines).override_failure_message("Not wrapped: " + layout) \
|
||||
.is_greater(1))
|
||||
|
||||
|
||||
func test_every_layout_holds_in_a_narrower_list() -> void:
|
||||
_panel.size.x = 640
|
||||
_panel_width = 640
|
||||
await _runner.simulate_frames(1)
|
||||
|
||||
await _each_layout(func(row: SongRow, layout: String) -> void:
|
||||
var text: Rect2 = row.song_list_label.get_global_rect()
|
||||
assert_bool(row.get_global_rect().grow(0.5).encloses(text)).override_failure_message(
|
||||
"Text outside the row: " + layout).is_true()
|
||||
if row.song_list_players.visible:
|
||||
assert_float(row.song_list_players.get_global_rect().position.x) \
|
||||
.override_failure_message("Pictures over the text: " + layout) \
|
||||
.is_greater_equal(text.end.x))
|
||||
|
||||
|
||||
func test_short_text_is_one_line_even_with_every_player() -> void:
|
||||
_add_song(SHORT, Settings.MAX_NUMBER_OF_PLAYERS)
|
||||
await _show()
|
||||
|
||||
assert_int(_rows()[0].song_list_label.get_line_count()).is_equal(1)
|
||||
|
||||
|
||||
func test_long_text_wraps_and_keeps_every_word() -> void:
|
||||
_add_song(LONG, 2)
|
||||
await _show()
|
||||
var label: Label = _rows()[0].song_list_label
|
||||
|
||||
assert_int(label.get_line_count()).is_greater(1)
|
||||
assert_str(label.text).ends_with("FINAL FANTASY III")
|
||||
assert_int(label.get_visible_line_count()).is_equal(label.get_line_count())
|
||||
|
||||
|
||||
# Height
|
||||
|
||||
func test_row_is_one_line_high_with_up_to_four_pictures() -> void:
|
||||
var one_line: float = await _one_line_height()
|
||||
for players: int in range(0, SongRow.MAX_PICTURES_PER_LINE + 1):
|
||||
_add_song(SHORT, players)
|
||||
await _show()
|
||||
|
||||
for row: SongRow in _rows():
|
||||
assert_float(row.size.y).override_failure_message(
|
||||
"%d pictures" % _pictures(row).size()).is_equal_approx(one_line, 0.5)
|
||||
|
||||
|
||||
func test_five_pictures_go_on_two_lines_of_three_and_two() -> void:
|
||||
_add_song(SHORT, 5)
|
||||
await _show()
|
||||
|
||||
assert_array(_lines_of_pictures(_rows()[0])).contains_exactly([3, 2])
|
||||
|
||||
|
||||
func test_seven_pictures_go_on_two_lines_of_four_and_three() -> void:
|
||||
_add_song(SHORT, 7)
|
||||
await _show()
|
||||
|
||||
assert_array(_lines_of_pictures(_rows()[0])).contains_exactly([4, 3])
|
||||
|
||||
|
||||
# How many pictures are on each line, top to bottom
|
||||
func _lines_of_pictures(row: SongRow) -> Array[int]:
|
||||
var by_top: Dictionary[float, int] = {}
|
||||
for picture: TextureRect in _pictures(row):
|
||||
var top: float = roundf(picture.global_position.y)
|
||||
by_top[top] = by_top.get(top, 0) + 1
|
||||
var tops: Array[float] = []
|
||||
tops.assign(by_top.keys())
|
||||
tops.sort()
|
||||
var lines: Array[int] = []
|
||||
for top: float in tops:
|
||||
lines.append(by_top[top])
|
||||
return lines
|
||||
|
||||
|
||||
func test_row_grows_to_fit_two_lines_of_pictures_and_centres_the_text() -> void:
|
||||
var one_line: float = await _one_line_height()
|
||||
_add_song(SHORT, 5)
|
||||
await _show()
|
||||
var row: SongRow = _rows()[0]
|
||||
var pictures: Rect2 = row.song_list_players.get_global_rect()
|
||||
|
||||
assert_float(row.size.y).is_greater(one_line)
|
||||
assert_float(pictures.size.y).is_equal_approx(
|
||||
SongRow.PICTURE_SIZE.y * 2 + row.song_list_players.get_theme_constant(
|
||||
&"separation"), 0.5)
|
||||
assert_bool(row.get_global_rect().encloses(pictures)).is_true()
|
||||
# The single line of text is in the middle, beside the pictures
|
||||
assert_int(row.song_list_label.vertical_alignment).is_equal(VERTICAL_ALIGNMENT_CENTER)
|
||||
assert_float(row.song_list_label.get_global_rect().get_center().y) \
|
||||
.is_equal_approx(pictures.get_center().y, 1.0)
|
||||
|
||||
|
||||
func test_pictures_are_centred_beside_text_on_many_lines() -> void:
|
||||
_add_song(LONG, 1)
|
||||
await _show()
|
||||
var row: SongRow = _rows()[0]
|
||||
var text: Rect2 = row.song_list_label.get_global_rect()
|
||||
var pictures: Rect2 = row.song_list_players.get_global_rect()
|
||||
|
||||
assert_int(row.song_list_label.get_line_count()).is_greater(1)
|
||||
assert_float(pictures.size.y).is_less(text.size.y)
|
||||
assert_float(pictures.get_center().y).is_equal_approx(text.get_center().y, 1.0)
|
||||
|
||||
|
||||
func test_every_picture_has_the_same_size() -> void:
|
||||
await _each_layout(func(row: SongRow, layout: String) -> void:
|
||||
for picture: TextureRect in _pictures(row):
|
||||
assert_vector(picture.size).override_failure_message(layout) \
|
||||
.is_equal(SongRow.PICTURE_SIZE))
|
||||
|
||||
|
||||
func test_rows_never_need_sideways_scrolling() -> void:
|
||||
Settings.is_debug = true
|
||||
for players: int in Settings.MAX_NUMBER_OF_PLAYERS + 1:
|
||||
_add_song(LONG, players)
|
||||
await _show()
|
||||
var scroll: ScrollContainer = _panel.get_node("ScrollContainer")
|
||||
|
||||
assert_bool(scroll.get_h_scroll_bar().visible).is_false()
|
||||
assert_float(_panel.size.x).is_equal(_panel_width)
|
||||
for row: SongRow in _rows():
|
||||
assert_float(row.get_global_rect().end.x) \
|
||||
.is_less_equal(scroll.get_global_rect().end.x + 0.5)
|
||||
|
||||
|
||||
# Pictures
|
||||
|
||||
func test_pictures_show_who_got_a_point_in_player_list_order() -> void:
|
||||
var song: SongObject = _add_song(SHORT, 0)
|
||||
# Points given in another order than the player list
|
||||
song.add_point(Settings.player_array[2].id)
|
||||
song.add_point(Settings.player_array[0].id)
|
||||
await _show()
|
||||
|
||||
var names: Array[String] = []
|
||||
for picture: TextureRect in _pictures(_rows()[0]):
|
||||
names.append(picture.tooltip_text)
|
||||
assert_array(names).contains_exactly(["Player 1", "Player 3"])
|
||||
assert_object(_pictures(_rows()[0])[0].texture).is_same(Settings.player_array[0].character)
|
||||
|
||||
|
||||
func test_pictures_are_redone_when_points_change() -> void:
|
||||
var song: SongObject = _add_song(SHORT, 4)
|
||||
await _show()
|
||||
song.add_point(Settings.player_array[4].id)
|
||||
|
||||
_rows()[0].update_players()
|
||||
await _runner.simulate_frames(2)
|
||||
|
||||
assert_array(_lines_of_pictures(_rows()[0])).contains_exactly([3, 2])
|
||||
|
||||
|
||||
func test_clicking_a_picture_clicks_the_song() -> void:
|
||||
_add_song(SHORT, 0)
|
||||
_add_song(SHORT, 3)
|
||||
await _show()
|
||||
var signals: GdUnitSignalAssert = assert_signal(monitor_signals(_panel))
|
||||
var picture: TextureRect = _pictures(_rows()[1])[1]
|
||||
|
||||
_runner.set_mouse_position(
|
||||
_panel.get_viewport().get_final_transform() * picture.get_global_rect().get_center())
|
||||
await _runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT)
|
||||
await _runner.await_input_processed()
|
||||
|
||||
await signals.is_emitted("song_clicked", [1])
|
||||
|
||||
|
||||
# Styles
|
||||
|
||||
func test_rows_alternate_and_the_playing_song_stands_out() -> void:
|
||||
for i: int in 4:
|
||||
_add_song(SHORT, 0)
|
||||
Playlist.song_object_array[2].is_playing = true
|
||||
await _show()
|
||||
|
||||
var styles: Array[StringName] = []
|
||||
for row: SongRow in _rows():
|
||||
styles.append(row.theme_type_variation)
|
||||
assert_array(styles).contains_exactly(
|
||||
[&"SongRow", &"SongRowOdd", &"SongRowPlaying", &"SongRowOdd"])
|
||||
assert_str(_rows()[2].song_list_label.theme_type_variation).is_equal("SongRowLabelPlaying")
|
||||
assert_str(_rows()[1].song_list_label.theme_type_variation).is_equal("SongRowLabel")
|
||||
|
||||
|
||||
func test_hovering_a_row_highlights_it_until_the_mouse_leaves() -> void:
|
||||
_add_song(SHORT, 0)
|
||||
_add_song(SHORT, 0)
|
||||
await _show()
|
||||
var row: SongRow = _rows()[1]
|
||||
|
||||
row.mouse_entered.emit()
|
||||
assert_str(row.theme_type_variation).is_equal("SongRowHover")
|
||||
|
||||
row.mouse_exited.emit()
|
||||
assert_str(row.theme_type_variation).is_equal("SongRowOdd")
|
||||
@@ -0,0 +1 @@
|
||||
uid://dnggvrk5thb2v
|
||||
@@ -32,6 +32,11 @@ const STYLES: Dictionary = {
|
||||
"HighlightMedium": "Label",
|
||||
"SongRowLabel": "Label",
|
||||
"SongRowLabelPlaying": "Label",
|
||||
"SongRowOdd": "PanelContainer",
|
||||
"SongRowHover": "PanelContainer",
|
||||
"SongRowPlaying": "PanelContainer",
|
||||
"SongRowPictureLine": "HBoxContainer",
|
||||
"SongRowPictureLines": "VBoxContainer",
|
||||
"StatisticsCard": "PanelContainer",
|
||||
"StatisticsCardHover": "PanelContainer",
|
||||
"StatisticsGrid": "GridContainer",
|
||||
|
||||
Reference in new issue
Block a user