diff --git a/Output/Languages/en.xml b/Output/Languages/en.xml
index d40203e7..8f0acff1 100644
--- a/Output/Languages/en.xml
+++ b/Output/Languages/en.xml
@@ -7,6 +7,9 @@
Save
Back
Start
+ Yes
+ No
+ Cancel
Audio streams
Video streams
Textures
@@ -280,6 +283,8 @@
Save snapshot
Delete snapshot
Webcam
+ Do you really want to delete the profile %s?
+ Do you want to save your changes?
Options
Game
Sound
diff --git a/Output/Themes/Changelog/Changelog_ScreenProfiles.txt b/Output/Themes/Changelog/Changelog_ScreenProfiles.txt
index 0f2cf2ff..f388cbb1 100644
--- a/Output/Themes/Changelog/Changelog_ScreenProfiles.txt
+++ b/Output/Themes/Changelog/Changelog_ScreenProfiles.txt
@@ -1,4 +1,8 @@
ScreenProfiles
+++++++++++
+Version 5:
+Add: , , , , (popup to confirm deleting a profile and to save changes before leaving)
+
++++++++++
Version 4:
Add:
diff --git a/Output/Themes/Changelog/Changelog_ScreenSing.txt b/Output/Themes/Changelog/Changelog_ScreenSing.txt
index 5289cf9a..99d141bd 100644
--- a/Output/Themes/Changelog/Changelog_ScreenSing.txt
+++ b/Output/Themes/Changelog/Changelog_ScreenSing.txt
@@ -1,4 +1,30 @@
ScreenSing
++++++++++
+Version 16
+
+Add:
+, , , , Icons of the pause buttons, they move with their button and use the text color of their button
+ Cover of the current song
+ Progress of the current song, the width is scaled by the progress
+ Only visible in vocals audio mode, keeps its horizontal distance to the left edge of
+ -
+
+
+
+ -
+ -
+
+Change:
+Visible pause buttons are placed without gaps in the slots of all pause buttons (sorted by Y, then X) in the order Continue, Skip, RestartRound, RestartGame, Cancel
+ Shows only the title of the song
+Statics starting with "StaticPause" that do not cover the whole screen are animated together with the pause buttons
+
++++++++++
+Version 15
+
+Add:
+ Darkens the game behind the pause menu (all statics starting with "StaticPause" are shown in the pause menu)
+
+++++++++
Version 14
diff --git a/Output/Themes/Changelog/Changelog_ScreenStatistics.txt b/Output/Themes/Changelog/Changelog_ScreenStatistics.txt
index 28ccf365..703413be 100644
--- a/Output/Themes/Changelog/Changelog_ScreenStatistics.txt
+++ b/Output/Themes/Changelog/Changelog_ScreenStatistics.txt
@@ -1,8 +1,16 @@
ScreenStatistics
+++++++++++
+Version 2:
+
+Change (same look as the party mode selection):
+ to use the skin ButtonTile with ButtonMainColor
+ uses the skin ButtonTile with ButtonSelColor and replaces the selected tile (like in ScreenParty)
+ to use the skin ButtonTile with ButtonMainColor
+Columns of the best list (, , , , ) moved 20 pixels down
+
++++++++++
Version 1:
-(2026 Oct 16)
New screen: statistics dashboard with four tiles (overview, recently sung, best list per difficulty, players)
Help text at the bottom of the screen
diff --git a/Output/Themes/Changelog/Changelog_ScreenStatisticsDetail.txt b/Output/Themes/Changelog/Changelog_ScreenStatisticsDetail.txt
index f228b95f..e66bfd50 100644
--- a/Output/Themes/Changelog/Changelog_ScreenStatisticsDetail.txt
+++ b/Output/Themes/Changelog/Changelog_ScreenStatisticsDetail.txt
@@ -1,5 +1,13 @@
ScreenStatisticsDetail
+++++++++++
+Version 2:
+(2026 Oct 18)
+
+Change (same look as the party mode selection):
+ uses the skin CoverTextBackground with StaticColorAlpha
+ use the skin ButtonTile with ButtonMainColor
+
++++++++++
Version 1:
(2026 Oct 16)
diff --git a/Output/Themes/Vocaluxe 2024/01_Standard.xml b/Output/Themes/Vocaluxe 2024/01_Standard.xml
index 7a8124ea..e42d6274 100644
--- a/Output/Themes/Vocaluxe 2024/01_Standard.xml
+++ b/Output/Themes/Vocaluxe 2024/01_Standard.xml
@@ -382,6 +382,7 @@
NoAvatar.png
SongMenu.png
PauseBG.png
+ PauseButton.png
EnergyBeam.png
SearchBar.png
PlaylistBG.png
diff --git a/Output/Themes/Vocaluxe 2024/02.xml b/Output/Themes/Vocaluxe 2024/02.xml
index fda8eb94..9798bffd 100644
--- a/Output/Themes/Vocaluxe 2024/02.xml
+++ b/Output/Themes/Vocaluxe 2024/02.xml
@@ -382,6 +382,7 @@
NoAvatar.png
SongMenu.png
PauseBG.png
+ PauseButton.png
EnergyBeam.png
SearchBar.png
PlaylistBG.png
diff --git a/Output/Themes/Vocaluxe 2024/03.xml b/Output/Themes/Vocaluxe 2024/03.xml
index a687f190..97dd35ac 100644
--- a/Output/Themes/Vocaluxe 2024/03.xml
+++ b/Output/Themes/Vocaluxe 2024/03.xml
@@ -382,6 +382,7 @@
NoAvatar.png
SongMenu.png
PauseBG.png
+ PauseButton.png
EnergyBeam.png
SearchBar.png
PlaylistBG.png
diff --git a/Output/Themes/Vocaluxe 2024/04.xml b/Output/Themes/Vocaluxe 2024/04.xml
index 94de6ff7..0585625c 100644
--- a/Output/Themes/Vocaluxe 2024/04.xml
+++ b/Output/Themes/Vocaluxe 2024/04.xml
@@ -382,6 +382,7 @@
NoAvatar.png
SongMenu.png
PauseBG.png
+ PauseButton.png
EnergyBeam.png
SearchBar.png
PlaylistBG.png
diff --git a/Output/Themes/Vocaluxe 2024/05.xml b/Output/Themes/Vocaluxe 2024/05.xml
index b272f2bc..194b797e 100644
--- a/Output/Themes/Vocaluxe 2024/05.xml
+++ b/Output/Themes/Vocaluxe 2024/05.xml
@@ -382,6 +382,7 @@
NoAvatar.png
SongMenu.png
PauseBG.png
+ PauseButton.png
EnergyBeam.png
SearchBar.png
PlaylistBG.png
diff --git a/Output/Themes/Vocaluxe 2024/06.xml b/Output/Themes/Vocaluxe 2024/06.xml
index 8cbb05bb..9b058273 100644
--- a/Output/Themes/Vocaluxe 2024/06.xml
+++ b/Output/Themes/Vocaluxe 2024/06.xml
@@ -382,6 +382,7 @@
NoAvatar.png
SongMenu.png
PauseBG.png
+ PauseButton.png
EnergyBeam.png
SearchBar.png
PlaylistBG.png
diff --git a/Output/Themes/Vocaluxe 2024/PauseButton.png b/Output/Themes/Vocaluxe 2024/PauseButton.png
new file mode 100644
index 00000000..a6d95449
Binary files /dev/null and b/Output/Themes/Vocaluxe 2024/PauseButton.png differ
diff --git a/Output/Themes/Vocaluxe 2024/Screens/ScreenProfiles.xml b/Output/Themes/Vocaluxe 2024/Screens/ScreenProfiles.xml
index 34efd80c..507d21ee 100644
--- a/Output/Themes/Vocaluxe 2024/Screens/ScreenProfiles.xml
+++ b/Output/Themes/Vocaluxe 2024/Screens/ScreenProfiles.xml
@@ -2,7 +2,7 @@
ScreenProfiles
- 4
+ 5
@@ -36,6 +36,17 @@
-1
+
+ PopupBG
+
+
+ 0
+ 0
+ 1920
+ 1080
+ -10
+
+
@@ -122,6 +133,20 @@
Outline
TR_SCREENPROFILES_ACTIVE
+
+ 960
+ 405
+ -11
+ 40.5
+ 900
+
+
+ Center
+ Center
+
+ Outline
+
+
+
+
+
diff --git a/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml b/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml
index 77b69377..c0e8fa49 100644
--- a/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml
+++ b/Output/Themes/Vocaluxe 2024/Screens/ScreenSing.xml
@@ -2,7 +2,7 @@
ScreenSing
- 14
+ 16
@@ -169,6 +169,22 @@
0
+
+
+
+ 0
+ 0
+ 0
+ 0.55
+
+
+ 0
+ 0
+ 1920
+ 1080
+ -2.05
+
+
PauseBG
@@ -180,6 +196,195 @@
-2.1
+
+ CoverTextBackground
+
+
+ 105
+ 240
+ 660
+ 720
+ -2.105
+
+
+
+ CoverTextBackground
+
+
+ 855
+ 240
+ 960
+ 720
+ -2.105
+
+
+
+ PlayIcon
+
+
+ 157.5
+ 285.5
+ 44
+ 44
+ -2.13
+
+
+
+ NextIcon
+
+
+ 157.5
+ 375.5
+ 44
+ 44
+ -2.13
+
+
+
+ RepeatIcon
+
+
+ 157.5
+ 465.5
+ 44
+ 44
+ -2.13
+
+
+
+ RepeatIcon
+
+
+ 157.5
+ 555.5
+ 44
+ 44
+ -2.13
+
+
+
+ CloseIcon
+
+
+ 157.5
+ 645.5
+ 44
+ 44
+ -2.13
+
+
+
+
+
+
+ 900
+ 285
+ 180
+ 180
+ -2.11
+
+
+
+ TimeLine
+
+ 0.2
+
+
+ 900
+ 490
+ 870
+ 6
+ -2.11
+
+
+
+ TimeLine
+
+
+ 900
+ 490
+ 870
+ 6
+ -2.12
+
+
+
+
+
+
+ 900
+ 560
+ 60
+ 60
+ -2.11
+
+
+
+
+
+
+ 1350
+ 560
+ 60
+ 60
+ -2.11
+
+
+
+
+
+
+ 900
+ 630
+ 60
+ 60
+ -2.11
+
+
+
+
+
+
+ 1350
+ 630
+ 60
+ 60
+ -2.11
+
+
+
+
+
+
+ 900
+ 700
+ 60
+ 60
+ -2.11
+
+
+
+
+
+
+ 1350
+ 700
+ 60
+ 60
+ -2.11
+
+
+
+ VocalsIcon
+
+
+ 1109
+ 784
+ 44
+ 44
+ -2.11
+
+
@@ -698,9 +903,9 @@
960
- 675
+ 55
-2.11
- 150
+ 130
0
@@ -711,31 +916,241 @@
TR_SCREENSING_PAUSE
- 960
- 15
+ 1110
+ 310
-2.11
- 60
- 0
-
-
- Center
- Center
-
- Normal
-
-
-
- 217.5
- 818
- -2.11
- 40.5
- 520
+ 48
+ 660
Left
Center
Outline
+
+
+
+ 1110
+ 370
+ -2.11
+ 36
+ 660
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 900
+ 508
+ -2.11
+ 30
+ 300
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 1770
+ 508
+ -2.11
+ 30
+ 300
+
+
+ Right
+ Center
+
+ Outline
+
+
+
+ 975
+ 572
+ -2.11
+ 36
+ 240
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 1320
+ 572
+ -2.11
+ 36
+ 0
+
+
+ Right
+ Center
+
+ Outline
+
+
+
+ 1425
+ 572
+ -2.11
+ 36
+ 240
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 1770
+ 572
+ -2.11
+ 36
+ 0
+
+
+ Right
+ Center
+
+ Outline
+
+
+
+ 975
+ 642
+ -2.11
+ 36
+ 240
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 1320
+ 642
+ -2.11
+ 36
+ 0
+
+
+ Right
+ Center
+
+ Outline
+
+
+
+ 1425
+ 642
+ -2.11
+ 36
+ 240
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 1770
+ 642
+ -2.11
+ 36
+ 0
+
+
+ Right
+ Center
+
+ Outline
+
+
+
+ 975
+ 712
+ -2.11
+ 36
+ 240
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 1320
+ 712
+ -2.11
+ 36
+ 0
+
+
+ Right
+ Center
+
+ Outline
+
+
+
+ 1425
+ 712
+ -2.11
+ 36
+ 240
+
+
+ Left
+ Center
+
+ Outline
+
+
+
+ 1770
+ 712
+ -2.11
+ 36
+ 0
+
+
+ Right
+ Center
+
+ Outline
+
+
+
+ 1335
+ 786
+ -2.11
+ 40.5
+ 810
+
+
+ Center
+ Center
+
+ Outline
TR_SCREENSING_VOCALSVOLUME
@@ -1367,180 +1782,140 @@
-
+
@@ -1614,43 +1989,43 @@
-
+ PauseButton
SelectSlideArrowLeft
SelectSlideArrowRight
- SelectSlide
+ PauseButton
SelectSlideArrowLeft
SelectSlideArrowRight
- 752
- 820
- 958
- 40
+ 900
+ 855
+ 870
+ 75
-2.11
- 757.5
- 822.5
- 35
- 35
+ 906
+ 868.5
+ 48
+ 48
-2.11
- 1667.5
- 822.5
- 35
- 35
+ 1716
+ 868.5
+ 48
+ 48
-2.11
-
-
+
+
-
-
+
+
40.5
- 75
+ 60
0
- 300
+ 140
Outline
Bold
5
diff --git a/Output/Themes/Vocaluxe 2024/Screens/ScreenStatistics.xml b/Output/Themes/Vocaluxe 2024/Screens/ScreenStatistics.xml
index eb5f0203..4ec0276a 100644
--- a/Output/Themes/Vocaluxe 2024/Screens/ScreenStatistics.xml
+++ b/Output/Themes/Vocaluxe 2024/Screens/ScreenStatistics.xml
@@ -2,7 +2,7 @@
ScreenStatistics
- 1
+ 2
@@ -26,13 +26,8 @@
-
-
- 0
- 0
- 0
- 0.45
-
+ ButtonTile
+
90
165
@@ -42,13 +37,8 @@
-
-
- 0
- 0
- 0
- 0.45
-
+ ButtonTile
+
975
165
@@ -58,13 +48,8 @@
-
-
- 0
- 0
- 0
- 0.45
-
+ ButtonTile
+
90
600
@@ -74,13 +59,8 @@
-
-
- 0
- 0
- 0
- 0.45
-
+ ButtonTile
+
975
600
@@ -90,13 +70,8 @@
-
-
- 0.2
- 0.8
- 0.99
- 0.25
-
+ ButtonTile
+
90
165
@@ -150,16 +125,11 @@
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
119
- 658
+ 678
257
300
0.8
@@ -170,7 +140,7 @@
131
- 728
+ 748
26
26
0
@@ -181,7 +151,7 @@
131
- 806
+ 826
26
26
0
@@ -192,23 +162,18 @@
131
- 884
+ 904
26
26
0
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
389
- 658
+ 678
257
300
0.8
@@ -219,7 +184,7 @@
401
- 728
+ 748
26
26
0
@@ -230,7 +195,7 @@
401
- 806
+ 826
26
26
0
@@ -241,23 +206,18 @@
401
- 884
+ 904
26
26
0
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
659
- 658
+ 678
257
300
0.8
@@ -268,7 +228,7 @@
671
- 728
+ 748
26
26
0
@@ -279,7 +239,7 @@
671
- 806
+ 826
26
26
0
@@ -290,7 +250,7 @@
671
- 884
+ 904
26
26
0
@@ -734,7 +694,7 @@
249
- 668
+ 688
-1
32
0
@@ -748,7 +708,7 @@
167
- 722
+ 742
-1
36
110
@@ -762,7 +722,7 @@
366
- 722
+ 742
-1
36
0
@@ -776,7 +736,7 @@
167
- 800
+ 820
-1
36
110
@@ -790,7 +750,7 @@
366
- 800
+ 820
-1
36
0
@@ -804,7 +764,7 @@
167
- 878
+ 898
-1
36
110
@@ -818,7 +778,7 @@
366
- 878
+ 898
-1
36
0
@@ -832,7 +792,7 @@
519
- 668
+ 688
-1
32
0
@@ -846,7 +806,7 @@
437
- 722
+ 742
-1
36
110
@@ -860,7 +820,7 @@
636
- 722
+ 742
-1
36
0
@@ -874,7 +834,7 @@
437
- 800
+ 820
-1
36
110
@@ -888,7 +848,7 @@
636
- 800
+ 820
-1
36
0
@@ -902,7 +862,7 @@
437
- 878
+ 898
-1
36
110
@@ -916,7 +876,7 @@
636
- 878
+ 898
-1
36
0
@@ -930,7 +890,7 @@
789
- 668
+ 688
-1
32
0
@@ -944,7 +904,7 @@
707
- 722
+ 742
-1
36
110
@@ -958,7 +918,7 @@
906
- 722
+ 742
-1
36
0
@@ -972,7 +932,7 @@
707
- 800
+ 820
-1
36
110
@@ -986,7 +946,7 @@
906
- 800
+ 820
-1
36
0
@@ -1000,7 +960,7 @@
707
- 878
+ 898
-1
36
110
@@ -1014,7 +974,7 @@
906
- 878
+ 898
-1
36
0
diff --git a/Output/Themes/Vocaluxe 2024/Screens/ScreenStatisticsDetail.xml b/Output/Themes/Vocaluxe 2024/Screens/ScreenStatisticsDetail.xml
index d165c777..e8c3ce68 100644
--- a/Output/Themes/Vocaluxe 2024/Screens/ScreenStatisticsDetail.xml
+++ b/Output/Themes/Vocaluxe 2024/Screens/ScreenStatisticsDetail.xml
@@ -2,7 +2,7 @@
ScreenStatisticsDetail
- 1
+ 2
@@ -26,13 +26,8 @@
-
-
- 0
- 0
- 0
- 0.45
-
+ CoverTextBackground
+
90
185
@@ -42,13 +37,8 @@
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
100
241
@@ -58,13 +48,8 @@
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
100
361
@@ -74,13 +59,8 @@
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
100
481
@@ -90,13 +70,8 @@
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
100
601
@@ -106,13 +81,8 @@
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
100
721
@@ -122,13 +92,8 @@
-
-
- 1
- 1
- 1
- 0.07
-
+ ButtonTile
+
100
841
diff --git a/Vocaluxe/Screens/CScreenNames.cs b/Vocaluxe/Screens/CScreenNames.cs
index b2306381..d2f7aa9a 100644
--- a/Vocaluxe/Screens/CScreenNames.cs
+++ b/Vocaluxe/Screens/CScreenNames.cs
@@ -266,6 +266,7 @@ namespace Vocaluxe.Screens
//Reset all values
_SelectingFastPlayerNr = 0;
_SelectingKeyboardActive = false;
+ _SelectingFast = false;
_NameSelections[_NameSelection].FastSelection(false, -1);
//Update Tiles-List
_NameSelections[_NameSelection].UpdateList();
@@ -363,7 +364,7 @@ namespace Vocaluxe.Screens
_SelectingFastPlayerNr = 6;
break;
default:
- _UpdatePlayerNumber();
+ _UpdatePlayerNumberIfChanged();
break;
}
@@ -542,7 +543,7 @@ namespace Vocaluxe.Screens
}
else
{
- _UpdatePlayerNumber();
+ _UpdatePlayerNumberIfChanged();
}
//Update Tiles-List
@@ -640,7 +641,7 @@ namespace Vocaluxe.Screens
{
if (_ProfilesChanged || _AvatarsChanged)
{
- _LoadProfiles();
+ _LoadProfiles(false);
}
for (var i = 1; i <= CGame.NumPlayers; i++)
@@ -662,9 +663,10 @@ namespace Vocaluxe.Screens
{
base.OnShow();
CRecord.Start();
+ _HasPlayedWarningSound = false;
_NameSelections[_NameSelection].Init();
- _LoadProfiles();
+ _LoadProfiles(true);
_SelectElement(_Buttons[_ButtonStart]);
}
@@ -689,7 +691,7 @@ namespace Vocaluxe.Screens
}
}
- private void _LoadProfiles()
+ private void _LoadProfiles(bool initDuetParts)
{
_NameSelections[_NameSelection].UpdateList();
@@ -709,6 +711,7 @@ namespace Vocaluxe.Screens
_Texts[_TextPlayer[i]].Text = CProfiles.GetPlayerName(CGame.Players[i].ProfileId, i + 1);
if (CGame.GetNumSongs() == 1 && firstSong.IsDuet)
{
+ var duetPart = _SelectSlides[_SelectSlideDuetPlayer[i]].Selection;
_SelectSlides[_SelectSlideDuetPlayer[i]].Clear();
_SelectSlides[_SelectSlideDuetPlayer[i]].Visible = i + 1 <= CGame.NumPlayers;
@@ -717,7 +720,7 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlideDuetPlayer[i]].AddValue(firstSong.Notes.VoiceNames[j]);
}
- _SelectSlides[_SelectSlideDuetPlayer[i]].Selection = i % 2;
+ _SelectSlides[_SelectSlideDuetPlayer[i]].Selection = initDuetParts || duetPart < 0 ? i % 2 : duetPart;
}
else
{
@@ -754,6 +757,14 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlidePlayerNumber].Selection = CConfig.Config.Game.NumPlayers - 1;
}
+ private void _UpdatePlayerNumberIfChanged()
+ {
+ if (_SelectSlides[_SelectSlidePlayerNumber].Selection + 1 != CConfig.Config.Game.NumPlayers)
+ {
+ _UpdatePlayerNumber();
+ }
+ }
+
private void _UpdatePlayerNumber()
{
CConfig.Config.Game.NumPlayers = _SelectSlides[_SelectSlidePlayerNumber].Selection + 1;
diff --git a/Vocaluxe/Screens/CScreenProfiles.cs b/Vocaluxe/Screens/CScreenProfiles.cs
index 074799bc..58444a8e 100644
--- a/Vocaluxe/Screens/CScreenProfiles.cs
+++ b/Vocaluxe/Screens/CScreenProfiles.cs
@@ -36,12 +36,19 @@ namespace Vocaluxe.Screens
PlayerName
}
+ enum EProfilesPopup
+ {
+ None,
+ Delete,
+ UnsavedChanges
+ }
+
public class CScreenProfiles : CMenu
{
// Version number for theme files. Increment it, if you've changed something on the theme files!
protected override int _ScreenVersion
{
- get { return 4; }
+ get { return 5; }
}
private const string _SelectSlideProfiles = "SelectSlideProfiles";
@@ -60,6 +67,11 @@ namespace Vocaluxe.Screens
private const string _ButtonTakeSnapshot = "ButtonTakeSnapshot";
private const string _NameSelection = "NameSelection";
private const string _StaticAvatar = "StaticAvatar";
+ private const string _StaticPopupBG = "StaticPopupBG";
+ private const string _TextPopup = "TextPopup";
+ private const string _ButtonPopupYes = "ButtonPopupYes";
+ private const string _ButtonPopupNo = "ButtonPopupNo";
+ private const string _ButtonPopupCancel = "ButtonPopupCancel";
private bool _ProfilesChanged;
private bool _AvatarsChanged;
private bool _SelectingKeyboardActive;
@@ -67,6 +79,9 @@ namespace Vocaluxe.Screens
private Dictionary _SelectSlideGuids = new Dictionary();
private EEditMode _EditMode;
+ private EProfilesPopup _Popup;
+ private bool _UnsavedChanges;
+ private string _NameBeforeEdit = string.Empty;
private CTextureRef _WebcamTexture;
private Bitmap _Snapshot;
@@ -76,9 +91,13 @@ namespace Vocaluxe.Screens
base.Init();
_ThemeButtons = new string[]
- { _ButtonPlayerName, _ButtonExit, _ButtonSave, _ButtonNew, _ButtonDelete, _ButtonWebcam, _ButtonSaveSnapshot, _ButtonDiscardSnapshot, _ButtonTakeSnapshot };
+ {
+ _ButtonPlayerName, _ButtonExit, _ButtonSave, _ButtonNew, _ButtonDelete, _ButtonWebcam, _ButtonSaveSnapshot, _ButtonDiscardSnapshot, _ButtonTakeSnapshot,
+ _ButtonPopupYes, _ButtonPopupNo, _ButtonPopupCancel
+ };
_ThemeSelectSlides = new string[] { _SelectSlideProfiles, _SelectSlideDifficulty, _SelectSlideAvatars, _SelectSlideUserRole, _SelectSlideActive };
- _ThemeStatics = new string[] { _StaticAvatar };
+ _ThemeStatics = new string[] { _StaticAvatar, _StaticPopupBG };
+ _ThemeTexts = new string[] { _TextPopup };
_ThemeNameSelections = new string[] { _NameSelection };
_EditMode = EEditMode.None;
@@ -100,10 +119,18 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlideUserRole].SetValues(0);
_SelectSlides[_SelectSlideActive].SetValues(0);
_Statics[_StaticAvatar].Aspect = EAspect.Crop;
+ _NameSelections[_NameSelection].ShowInactive = true;
+ _ShowPopup(EProfilesPopup.None);
}
public override bool HandleInput(SKeyEvent keyEvent)
{
+ if (_Popup != EProfilesPopup.None)
+ {
+ _HandlePopupInput(keyEvent);
+ return true;
+ }
+
if (_SelectingKeyboardActive)
{
switch (keyEvent.Key)
@@ -163,6 +190,7 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlideProfiles].RenameValue(
CProfiles.AddGetPlayerName(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag), keyEvent.Unicode));
_ProfilesChanged = true;
+ _UnsavedChanges = true;
break;
}
}
@@ -173,11 +201,11 @@ namespace Vocaluxe.Screens
case Keys.Escape:
if (_EditMode == EEditMode.PlayerName)
{
- _EditMode = EEditMode.None;
+ _EndNameEdit(true);
}
else
{
- CGraphics.FadeTo(EScreen.Main);
+ _Leave();
}
break;
@@ -185,7 +213,7 @@ namespace Vocaluxe.Screens
case Keys.Enter:
if (_Buttons[_ButtonExit].Selected)
{
- CGraphics.FadeTo(EScreen.Main);
+ _Leave();
}
else if (_Buttons[_ButtonSave].Selected)
{
@@ -197,18 +225,11 @@ namespace Vocaluxe.Screens
}
else if (_Buttons[_ButtonPlayerName].Selected)
{
- if (CProfiles.NumProfiles > 0 && _EditMode != EEditMode.PlayerName)
- {
- _EditMode = EEditMode.PlayerName;
- }
- else
- {
- _EditMode = EEditMode.None;
- }
+ _ToggleNameEdit();
}
else if (_Buttons[_ButtonDelete].Selected)
{
- _DeleteProfile();
+ _RequestDeleteProfile();
}
else if (_Buttons[_ButtonWebcam].Selected)
{
@@ -230,44 +251,27 @@ namespace Vocaluxe.Screens
break;
case Keys.Back:
+ case Keys.Delete:
if (_EditMode == EEditMode.PlayerName)
{
_SelectSlides[_SelectSlideProfiles].RenameValue(
CProfiles.GetDeleteCharInPlayerName(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag)));
_ProfilesChanged = true;
+ _UnsavedChanges = true;
+ }
+ else if (keyEvent.Key == Keys.Delete)
+ {
+ _RequestDeleteProfile();
}
else
{
- CGraphics.FadeTo(EScreen.Main);
+ _Leave();
}
break;
-
- case Keys.Delete:
- _DeleteProfile();
- break;
}
- if (_SelectSlides[_SelectSlideDifficulty].Selected)
- {
- CProfiles.SetDifficulty(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- (EGameDifficulty)_SelectSlides[_SelectSlideDifficulty].Selection);
- }
- else if (_SelectSlides[_SelectSlideAvatars].Selected)
- {
- CProfiles.SetAvatar(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- _SelectSlides[_SelectSlideAvatars].SelectedTag);
- }
- else if (_SelectSlides[_SelectSlideUserRole].Selected)
- {
- CProfiles.SetUserRoleProfile(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- (EUserRole)_SelectSlides[_SelectSlideUserRole].Selection);
- }
- else if (_SelectSlides[_SelectSlideActive].Selected)
- {
- CProfiles.SetActive(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- (EOffOn)_SelectSlides[_SelectSlideActive].Selection);
- }
+ _ApplySelectSlideValues();
}
return true;
@@ -275,6 +279,12 @@ namespace Vocaluxe.Screens
public override bool HandleMouse(SMouseEvent mouseEvent)
{
+ if (_Popup != EProfilesPopup.None)
+ {
+ _HandlePopupMouse(mouseEvent);
+ return true;
+ }
+
if (_EditMode == EEditMode.None)
{
base.HandleMouse(mouseEvent);
@@ -293,7 +303,7 @@ namespace Vocaluxe.Screens
{
if (_Buttons[_ButtonExit].Selected)
{
- CGraphics.FadeTo(EScreen.Main);
+ _Leave();
}
else if (_Buttons[_ButtonSave].Selected)
{
@@ -305,42 +315,16 @@ namespace Vocaluxe.Screens
}
else if (_Buttons[_ButtonDelete].Selected)
{
- _DeleteProfile();
+ _RequestDeleteProfile();
}
else if (_Buttons[_ButtonPlayerName].Selected)
{
- if (CProfiles.NumProfiles > 0 && _EditMode != EEditMode.PlayerName)
- {
- _EditMode = EEditMode.PlayerName;
- }
- else
- {
- _EditMode = EEditMode.None;
- }
+ _ToggleNameEdit();
}
- else if (_SelectSlides[_SelectSlideDifficulty].Selected)
+ else if (_SelectSlides[_SelectSlideDifficulty].Selected || _SelectSlides[_SelectSlideAvatars].Selected ||
+ _SelectSlides[_SelectSlideUserRole].Selected || _SelectSlides[_SelectSlideActive].Selected)
{
- CProfiles.SetDifficulty(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- (EGameDifficulty)_SelectSlides[_SelectSlideDifficulty].Selection);
- }
- else if (_SelectSlides[_SelectSlideAvatars].Selected)
- {
- CProfiles.SetAvatar(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- _SelectSlides[_SelectSlideAvatars].SelectedTag);
- if (CWebcam.IsDeviceAvailable() && _WebcamTexture != null)
- {
- _OnDiscardSnapshot();
- }
- }
- else if (_SelectSlides[_SelectSlideUserRole].Selected)
- {
- CProfiles.SetUserRoleProfile(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- (EUserRole)_SelectSlides[_SelectSlideUserRole].Selection);
- }
- else if (_SelectSlides[_SelectSlideActive].Selected)
- {
- CProfiles.SetActive(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag),
- (EOffOn)_SelectSlides[_SelectSlideActive].Selection);
+ _ApplySelectSlideValues();
}
else if (_Buttons[_ButtonWebcam].Selected)
{
@@ -362,7 +346,7 @@ namespace Vocaluxe.Screens
if (mouseEvent.RB)
{
- CGraphics.FadeTo(EScreen.Main);
+ _Leave();
}
if (mouseEvent.Wheel != 0 && CHelper.IsInBounds(_NameSelections[_NameSelection].Rect, mouseEvent))
@@ -435,9 +419,260 @@ namespace Vocaluxe.Screens
base.OnClose();
_EditMode = EEditMode.None;
_SelectingKeyboardActive = false;
+ _ShowPopup(EProfilesPopup.None);
_OnDiscardSnapshot();
}
+ private void _Leave()
+ {
+ _EndNameEdit(false);
+ if (_UnsavedChanges)
+ {
+ _ShowPopup(EProfilesPopup.UnsavedChanges);
+ return;
+ }
+
+ CGraphics.FadeTo(EScreen.Main);
+ }
+
+ private void _DiscardChanges()
+ {
+ _UnsavedChanges = false;
+ CProfiles.LoadProfiles();
+ }
+
+ private void _ShowPopup(EProfilesPopup popup)
+ {
+ _Popup = popup;
+ var visible = popup != EProfilesPopup.None;
+ _Statics[_StaticPopupBG].Visible = visible;
+ _Texts[_TextPopup].Visible = visible;
+ _Buttons[_ButtonPopupYes].Visible = visible;
+ _Buttons[_ButtonPopupNo].Visible = popup == EProfilesPopup.UnsavedChanges;
+ _Buttons[_ButtonPopupCancel].Visible = visible;
+
+ switch (popup)
+ {
+ case EProfilesPopup.Delete:
+ var name = CProfiles.GetPlayerName(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag));
+ _Texts[_TextPopup].Text = CLanguage.Translate("TR_SCREENPROFILES_POPUP_DELETE").Replace("%s", name);
+ _SelectElement(_Buttons[_ButtonPopupCancel]);
+ break;
+
+ case EProfilesPopup.UnsavedChanges:
+ _Texts[_TextPopup].Text = CLanguage.Translate("TR_SCREENPROFILES_POPUP_UNSAVED");
+ _SelectElement(_Buttons[_ButtonPopupYes]);
+ break;
+ }
+ }
+
+ private List _GetPopupButtons()
+ {
+ return new[] { _ButtonPopupYes, _ButtonPopupNo, _ButtonPopupCancel }.Where(name => _Buttons[name].Visible).ToList();
+ }
+
+ private void _HandlePopupInput(SKeyEvent keyEvent)
+ {
+ if (keyEvent.KeyPressed)
+ {
+ return;
+ }
+
+ var buttons = _GetPopupButtons();
+ var selected = buttons.FindIndex(name => _Buttons[name].Selected);
+ switch (keyEvent.Key)
+ {
+ case Keys.Left:
+ case Keys.Up:
+ _SelectElement(_Buttons[buttons[(selected - 1 + buttons.Count) % buttons.Count]]);
+ break;
+
+ case Keys.Right:
+ case Keys.Down:
+ case Keys.Tab:
+ _SelectElement(_Buttons[buttons[(selected + 1) % buttons.Count]]);
+ break;
+
+ case Keys.Escape:
+ case Keys.Back:
+ _ExecutePopupButton(_ButtonPopupCancel);
+ break;
+
+ case Keys.Enter:
+ _ExecutePopupButton(selected >= 0 ? buttons[selected] : _ButtonPopupCancel);
+ break;
+ }
+ }
+
+ private void _HandlePopupMouse(SMouseEvent mouseEvent)
+ {
+ foreach (var name in _GetPopupButtons())
+ {
+ if (!CHelper.IsInBounds(_Buttons[name].Rect, mouseEvent))
+ {
+ continue;
+ }
+
+ if (!_Buttons[name].Selected)
+ {
+ _SelectElement(_Buttons[name]);
+ }
+
+ if (mouseEvent.LB)
+ {
+ _ExecutePopupButton(name);
+ }
+
+ return;
+ }
+
+ if (mouseEvent.RB)
+ {
+ _ExecutePopupButton(_ButtonPopupCancel);
+ }
+ }
+
+ private void _ExecutePopupButton(string button)
+ {
+ var popup = _Popup;
+ _ShowPopup(EProfilesPopup.None);
+
+ if (popup == EProfilesPopup.Delete)
+ {
+ if (button == _ButtonPopupYes)
+ {
+ _DeleteProfile();
+ }
+
+ _SelectElement(_Buttons[_ButtonDelete]);
+ }
+ else if (popup == EProfilesPopup.UnsavedChanges)
+ {
+ if (button == _ButtonPopupCancel)
+ {
+ _SelectElement(_Buttons[_ButtonSave]);
+ return;
+ }
+
+ if (button == _ButtonPopupYes)
+ {
+ _SaveProfiles();
+ }
+ else
+ {
+ _DiscardChanges();
+ }
+
+ CGraphics.FadeTo(EScreen.Main);
+ }
+ }
+
+ private void _RequestDeleteProfile()
+ {
+ _EndNameEdit(false);
+ if (!CProfiles.IsProfileIdValid(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag)))
+ {
+ return;
+ }
+
+ _ShowPopup(EProfilesPopup.Delete);
+ }
+
+ private void _ToggleNameEdit()
+ {
+ if (_EditMode == EEditMode.PlayerName)
+ {
+ _EndNameEdit(false);
+ }
+ else
+ {
+ _StartNameEdit();
+ }
+ }
+
+ private void _StartNameEdit()
+ {
+ var id = _GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag);
+ if (!CProfiles.IsProfileIdValid(id))
+ {
+ return;
+ }
+
+ _NameBeforeEdit = CProfiles.GetPlayerName(id);
+ _EditMode = EEditMode.PlayerName;
+ }
+
+ private void _EndNameEdit(bool restore)
+ {
+ if (_EditMode != EEditMode.PlayerName)
+ {
+ return;
+ }
+
+ _EditMode = EEditMode.None;
+ var id = _GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag);
+ if (!restore && !string.IsNullOrWhiteSpace(CProfiles.GetPlayerName(id)))
+ {
+ return;
+ }
+
+ var name = string.IsNullOrWhiteSpace(_NameBeforeEdit) ? CProfiles.GetPlayerName(Guid.Empty) : _NameBeforeEdit;
+ CProfiles.SetPlayerName(id, name);
+ _SelectSlides[_SelectSlideProfiles].RenameValue(name);
+ _ProfilesChanged = true;
+ }
+
+ private void _ApplySelectSlideValues()
+ {
+ var id = _GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag);
+ if (!CProfiles.IsProfileIdValid(id))
+ {
+ return;
+ }
+
+ if (_SelectSlides[_SelectSlideDifficulty].Selected)
+ {
+ var difficulty = (EGameDifficulty)_SelectSlides[_SelectSlideDifficulty].Selection;
+ if (difficulty != CProfiles.GetDifficulty(id))
+ {
+ CProfiles.SetDifficulty(id, difficulty);
+ _UnsavedChanges = true;
+ }
+ }
+ else if (_SelectSlides[_SelectSlideAvatars].Selected)
+ {
+ var avatarId = _SelectSlides[_SelectSlideAvatars].SelectedTag;
+ if (avatarId != CProfiles.GetAvatarId(id))
+ {
+ CProfiles.SetAvatar(id, avatarId);
+ _UnsavedChanges = true;
+ if (_WebcamTexture != null || CWebcam.IsCapturing())
+ {
+ _ResetSnapshot();
+ }
+ }
+ }
+ else if (_SelectSlides[_SelectSlideUserRole].Selected)
+ {
+ var userRole = (EUserRole)_SelectSlides[_SelectSlideUserRole].Selection;
+ if (userRole != CProfiles.GetUserRoleProfile(id))
+ {
+ CProfiles.SetUserRoleProfile(id, userRole);
+ _UnsavedChanges = true;
+ }
+ }
+ else if (_SelectSlides[_SelectSlideActive].Selected)
+ {
+ var active = (EOffOn)_SelectSlides[_SelectSlideActive].Selection;
+ if (active != CProfiles.GetActive(id))
+ {
+ CProfiles.SetActive(id, active);
+ _UnsavedChanges = true;
+ _NameSelections[_NameSelection].UpdateList();
+ }
+ }
+ }
+
private void _OnProfileChanged(EProfileChangedFlags flags)
{
if (EProfileChangedFlags.Avatar == (EProfileChangedFlags.Avatar & flags))
@@ -484,14 +719,23 @@ namespace Vocaluxe.Screens
private void _OnDiscardSnapshot()
{
+ _ResetSnapshot();
+ _SelectElement(_Buttons[_ButtonWebcam]);
+ }
+
+ private void _ResetSnapshot()
+ {
+ if (CWebcam.IsCapturing())
+ {
+ CWebcam.Stop();
+ }
+
_Snapshot = null;
CDraw.RemoveTexture(ref _WebcamTexture);
_Buttons[_ButtonSaveSnapshot].Visible = false;
_Buttons[_ButtonDiscardSnapshot].Visible = false;
_Buttons[_ButtonTakeSnapshot].Visible = false;
_Buttons[_ButtonWebcam].Visible = CWebcam.IsDeviceAvailable();
-
- _SelectElement(_Buttons[_ButtonWebcam]);
}
private void _OnSaveSnapshot()
@@ -509,6 +753,7 @@ namespace Vocaluxe.Screens
var id = CProfiles.NewAvatar(file);
CProfiles.SetAvatar(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag), id);
+ _UnsavedChanges = true;
_LoadAvatars(false);
_NameSelections[_NameSelection].UpdateList();
@@ -535,7 +780,7 @@ namespace Vocaluxe.Screens
private void _NewProfile()
{
- _EditMode = EEditMode.None;
+ _EndNameEdit(false);
var id = CProfiles.NewProfile();
_LoadProfiles(false);
var num = CProfiles.NumProfiles;
@@ -546,20 +791,23 @@ namespace Vocaluxe.Screens
_NameSelections[_NameSelection].UpdateList();
_SelectElement(_Buttons[_ButtonPlayerName]);
+ _UnsavedChanges = true;
+ _NameBeforeEdit = string.Empty;
_EditMode = EEditMode.PlayerName;
}
private void _SaveProfiles()
{
- _EditMode = EEditMode.None;
+ _EndNameEdit(false);
CProfiles.SaveProfiles();
+ _UnsavedChanges = false;
_LoadProfiles(true);
_NameSelections[_NameSelection].UpdateList();
}
private void _DeleteProfile()
{
- _EditMode = EEditMode.None;
+ _EndNameEdit(false);
CProfiles.DeleteProfile(_GetIdFromTag(_SelectSlides[_SelectSlideProfiles].SelectedTag));
_SelectSlideGuids.Remove(_SelectSlides[_SelectSlideProfiles].SelectedTag);
@@ -660,6 +908,7 @@ namespace Vocaluxe.Screens
return;
}
+ _EndNameEdit(false);
var entry = _SelectSlideGuids.FirstOrDefault(x => x.Value.Equals(profileId));
if (_SelectSlideGuids.ContainsKey(entry.Key))
{
diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs
index 7894bdae..e6330cfc 100644
--- a/Vocaluxe/Screens/CScreenSing.cs
+++ b/Vocaluxe/Screens/CScreenSing.cs
@@ -39,7 +39,7 @@ namespace Vocaluxe.Screens
// Version number for theme files. Increment it, if you've changed something on the theme files!
protected override int _ScreenVersion
{
- get { return 14; }
+ get { return 16; }
}
private struct STimeRect
@@ -57,6 +57,11 @@ namespace Vocaluxe.Screens
private const string _TextMedleyCountdown = "TextMedleyCountdown";
private const string _TextPauseSongName = "TextPauseSongName";
private const string _TextPauseVocalsVolume = "TextPauseVocalsVolume";
+ private const string _TextPauseArtist = "TextPauseArtist";
+ private const string _TextPauseTimeCurrent = "TextPauseTimeCurrent";
+ private const string _TextPauseTimeRemaining = "TextPauseTimeRemaining";
+ private const string _TextPauseName = "TextPauseNameP";
+ private const string _TextPauseScore = "TextPauseScoreP";
private string[,,] _TextScores;
private string[,,] _TextNames;
private List _TextsPause;
@@ -75,6 +80,10 @@ namespace Vocaluxe.Screens
private const string _StaticLyricHelperDuet = "StaticLyricHelperDuet";
private const string _StaticLyricHelperTop = "StaticLyricHelperTop";
private const string _StaticCountdownRing = "StaticCountdownRing";
+ private const string _StaticPauseCover = "StaticPauseCover";
+ private const string _StaticPauseTimeLineProgress = "StaticPauseTimeLineProgress";
+ private const string _StaticPauseVocalsIcon = "StaticPauseVocalsIcon";
+ private const string _StaticPauseAvatar = "StaticPauseAvatarP";
private List _StaticsPause;
private string[,,] _StaticScores;
@@ -89,6 +98,14 @@ namespace Vocaluxe.Screens
private const string _ButtonRestartGame = "ButtonRestartGame";
private const string _ButtonSkip = "ButtonSkip";
+ private static readonly string[] _PauseButtons = { _ButtonContinue, _ButtonSkip, _ButtonRestartRound, _ButtonRestartGame, _ButtonCancel };
+ private static readonly string[] _PauseIcons =
+ { "StaticPauseIconContinue", "StaticPauseIconSkip", "StaticPauseIconRestartRound", "StaticPauseIconRestartGame", "StaticPauseIconCancel" };
+ private SRectF[] _PauseButtonSlots;
+ private SRectF[] _PauseIconOffsets;
+ private float _PauseTimeLineW;
+ private float _PauseVocalsIconOffset;
+
private const string _SelectSlidePauseVocalsVolume = "SelectSlidePauseVocalsVolume";
private List _SelectSlidesPause;
@@ -261,6 +278,18 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlidePauseVocalsVolume].Selection = CConfig.VocalsVolume / 5;
_Statics[_StaticCountdownRing].Visible = false;
+ _PauseButtonSlots = _PauseButtons.Select(b => _Buttons[b].Rect).OrderBy(r => r.Y).ThenBy(r => r.X).ToArray();
+ _PauseIconOffsets = new SRectF[_PauseButtons.Length];
+ for (var i = 0; i < _PauseButtons.Length; i++)
+ {
+ var button = _Buttons[_PauseButtons[i]].Rect;
+ var icon = _Statics[_PauseIcons[i]].Rect;
+ _PauseIconOffsets[i] = new SRectF(icon.X - button.X, icon.Y - button.Y, icon.W, icon.H, icon.Z);
+ }
+
+ _PauseTimeLineW = _Statics[_StaticPauseTimeLineProgress].W;
+ _PauseVocalsIconOffset = _Statics[_StaticPauseVocalsIcon].X - _Texts[_TextPauseVocalsVolume].Rect.X;
+
//Automatically find statics and texts with pause prefix
foreach (var s in _Statics.Where(s => s.ThemeLoaded && s.GetThemeName().StartsWith("StaticPause")))
{
@@ -272,7 +301,7 @@ namespace Vocaluxe.Screens
_TextsPause.Add(t.GetThemeName());
}
- foreach (var t in _Texts.Where(s => s.ThemeLoaded && s.GetThemeName().StartsWith("SelectSlidePause")))
+ foreach (var t in _SelectSlides.Where(s => s.ThemeLoaded && s.GetThemeName().StartsWith("SelectSlidePause")))
{
_SelectSlidesPause.Add(t.GetThemeName());
}
@@ -290,7 +319,7 @@ namespace Vocaluxe.Screens
_TogglePause();
if (_Pause)
{
- _SelectElement(_Buttons[_ButtonCancel]);
+ _SelectElement(_Buttons[_ButtonContinue]);
}
break;
@@ -332,16 +361,16 @@ namespace Vocaluxe.Screens
break;
case Keys.S:
- if (CGame.NumRounds > CGame.RoundNr)
+ if (keyEvent.ModCtrl)
{
- if (keyEvent.ModCtrl)
+ if (CGame.NumRounds > CGame.RoundNr)
{
_NextSong();
}
- }
- else
- {
- _ShowInfoText(CBase.Language.Translate("TR_SCREENSING_NOMORESONGS"));
+ else
+ {
+ _ShowInfoText(CBase.Language.Translate("TR_SCREENSING_NOMORESONGS"));
+ }
}
break;
@@ -650,6 +679,7 @@ namespace Vocaluxe.Screens
else if (_StartDelayed)
{
_UpdateStartCountdown();
+ _UpdateRatingPopups();
return true;
}
@@ -1001,7 +1031,7 @@ namespace Vocaluxe.Screens
}
}
- private void _UpdateDuetNames(CText textName, Stopwatch timer)
+ private void _UpdateDuetNames(CText textName, Stopwatch timer, CLyric lyric)
{
if (timer.IsRunning)
{
@@ -1029,7 +1059,7 @@ namespace Vocaluxe.Screens
timer.Stop();
}
}
- else if (!timer.IsRunning && timer.ElapsedMilliseconds == 0 && _Lyrics[_LyricMainTop].Alpha > 0 && CGame.GetSong().IsDuet)
+ else if (!timer.IsRunning && timer.ElapsedMilliseconds == 0 && lyric.Alpha > 0 && CGame.GetSong().IsDuet)
{
timer.Start();
}
@@ -1047,42 +1077,9 @@ namespace Vocaluxe.Screens
}
//Timer for first duet-part
- _UpdateDuetNames(_Texts[_TextDuetName1], _TimerDuetText1);
+ _UpdateDuetNames(_Texts[_TextDuetName1], _TimerDuetText1, _Lyrics[_LyricMainTop]);
//Timer for second duet-part
- if (_TimerDuetText2.IsRunning)
- {
- var t = _TimerDuetText2.ElapsedMilliseconds / 1000f;
- if (t < 10f)
- {
- _Texts[_TextDuetName2].Visible = true;
-
- if (t < 3f)
- {
- _Texts[_TextDuetName2].Color.A = (3f - (3f - t)) / 3f;
- }
- else if (t < 7f)
- {
- _Texts[_TextDuetName2].Color.A = 1f;
- }
- else
- {
- _Texts[_TextDuetName2].Color.A = (3f - (t - 7f)) / 3f;
- }
- }
- else
- {
- _Texts[_TextDuetName2].Visible = false;
- _TimerDuetText2.Stop();
- }
- }
- else if (!_TimerDuetText2.IsRunning && _TimerDuetText2.ElapsedMilliseconds == 0 && _Lyrics[_LyricMainDuet].Alpha > 0 && CGame.GetSong().IsDuet)
- {
- _TimerDuetText2.Start();
- }
- else
- {
- _Texts[_TextDuetName2].Visible = false;
- }
+ _UpdateDuetNames(_Texts[_TextDuetName2], _TimerDuetText2, _Lyrics[_LyricMainDuet]);
}
private void _UpdateTimeLine()
@@ -1298,6 +1295,11 @@ namespace Vocaluxe.Screens
}
}
+ if (_Pause)
+ {
+ _UpdatePauseIconColors();
+ }
+
var pauseAnimation = _GetPauseAnimation(out var pauseAlpha, out var pauseScale);
if (pauseAnimation)
{
@@ -1457,14 +1459,28 @@ namespace Vocaluxe.Screens
_Texts[_TextMedleyCountdown].Text = string.Empty;
_Texts[_TextMedleyCountdown].Visible = true;
+ _SetPlayerInfoAlpha(0f);
return;
}
_StartSongNow();
}
+ private void _SetPlayerInfoAlpha(float alpha)
+ {
+ for (var p = 0; p < CGame.NumPlayers; p++)
+ {
+ _Statics[_PlayerStaticAvatar[p]].Alpha = alpha;
+ _Statics[_PlayerStaticScore[p]].Alpha = alpha;
+ _Texts[_PlayerTextName[p]].Alpha = alpha;
+ _Texts[_PlayerTextScore[p]].Alpha = alpha;
+ _ProgressBars[_PlayerProgressBarRating[p]].Alpha = alpha;
+ }
+ }
+
private void _StartSongNow()
{
+ _SetPlayerInfoAlpha(1f);
_PrepareTimeLine();
CSound.Play(_CurrentStream);
@@ -1625,7 +1641,7 @@ namespace Vocaluxe.Screens
_PauseAnimationBackgrounds.Clear();
_PauseAnimationElements.Clear();
- _PauseAnimationBackgrounds.AddRange(_StaticsPause.Select(s => (IMenuElement)_Statics[s]).Where(s => s.Visible));
+ _PauseAnimationBackgrounds.AddRange(_StaticsPause.Select(s => (IMenuElement)_Statics[s]).Where(s => s.Visible && _IsFullScreen(s)));
var elements = new List
{
@@ -1636,9 +1652,89 @@ namespace Vocaluxe.Screens
_Buttons[_ButtonRestartRound],
_SelectSlides[_SelectSlidePauseVocalsVolume]
};
+ elements.AddRange(_StaticsPause.Select(s => (IMenuElement)_Statics[s]).Where(s => !_IsFullScreen(s)));
elements.AddRange(_SelectSlidesPause.Select(s => (IMenuElement)_SelectSlides[s]));
elements.AddRange(_TextsPause.Select(s => (IMenuElement)_Texts[s]));
- _PauseAnimationElements.AddRange(elements.Distinct().Where(e => e.Visible));
+ _PauseAnimationElements.AddRange(elements.Distinct().Where(e => e.Visible).OrderByDescending(e => e.Rect.Z));
+ }
+
+ private static bool _IsFullScreen(IMenuElement element)
+ {
+ return element.Rect.W >= CSettings.RenderW && element.Rect.H >= CSettings.RenderH;
+ }
+
+ private void _ArrangePauseButtons()
+ {
+ var slot = 0;
+ for (var i = 0; i < _PauseButtons.Length; i++)
+ {
+ var button = _Buttons[_PauseButtons[i]];
+ var icon = _Statics[_PauseIcons[i]];
+ icon.Visible = button.Visible;
+ if (!button.Visible)
+ {
+ continue;
+ }
+
+ var rect = _PauseButtonSlots[slot++];
+ button.X = rect.X;
+ button.Y = rect.Y;
+ icon.X = rect.X + _PauseIconOffsets[i].X;
+ icon.Y = rect.Y + _PauseIconOffsets[i].Y;
+ }
+ }
+
+ private void _UpdatePauseIconColors()
+ {
+ for (var i = 0; i < _PauseButtons.Length; i++)
+ {
+ var text = _Buttons[_PauseButtons[i]].Text;
+ _Statics[_PauseIcons[i]].Color = text.Selected ? text.SelColor : text.Color;
+ }
+ }
+
+ private void _UpdatePauseInfo()
+ {
+ var song = CGame.GetSong();
+ if (song != null)
+ {
+ var endTime = Math.Abs(song.End) > 0.001 ? song.End : CSound.GetLength(_CurrentStream);
+ var length = endTime - song.Start;
+ var currentTime = Math.Max(0f, _CurrentTime - song.Start);
+
+ _Texts[_TextPauseTimeCurrent].Text = _FormatPauseTime(currentTime);
+ _Texts[_TextPauseTimeRemaining].Text = "-" + _FormatPauseTime(Math.Max(0f, endTime - _CurrentTime));
+ _Statics[_StaticPauseTimeLineProgress].W = length > 0f ? _PauseTimeLineW * Math.Min(1f, currentTime / length) : 0f;
+ }
+
+ for (var i = 0; i < CSettings.MaxNumPlayer; i++)
+ {
+ var avatar = _Statics[_StaticPauseAvatar + (i + 1)];
+ var name = _Texts[_TextPauseName + (i + 1)];
+ var score = _Texts[_TextPauseScore + (i + 1)];
+ var visible = i < CGame.NumPlayers && CProfiles.IsProfileIdValid(CGame.Players[i].ProfileId);
+
+ avatar.Visible = visible;
+ name.Visible = visible;
+ score.Visible = visible;
+ if (!visible)
+ {
+ continue;
+ }
+
+ avatar.Texture = CProfiles.GetAvatarTextureFromProfile(CGame.Players[i].ProfileId) ?? CBase.Themes.GetSkinTexture("NoAvatar", PartyModeId);
+ avatar.Aspect = EAspect.Crop;
+ name.Text = CProfiles.GetPlayerName(CGame.Players[i].ProfileId);
+ score.Text = CGame.Players[i].Points.ToString(CGame.Players[i].Points < 10000 ? "0000" : "00000");
+ score.Color = new SColorF(CBase.Themes.GetPlayerColor(i + 1), score.Color.A);
+ }
+ }
+
+ private static string _FormatPauseTime(float time)
+ {
+ var min = (int)Math.Floor(time / 60f);
+ var sec = (int)(time - min * 60f);
+ return min.ToString("00") + ":" + sec.ToString("00");
}
private void _SetPause(bool paused)
@@ -1676,6 +1772,14 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlidePauseVocalsVolume].Visible = _Pause && CGame.AudioMode == EAudioMode.TR_AUDIOMODE_VOCALS;
_Texts[_TextPauseVocalsVolume].Visible = _Pause && CGame.AudioMode == EAudioMode.TR_AUDIOMODE_VOCALS;
+ _Statics[_StaticPauseVocalsIcon].Visible = _Pause && CGame.AudioMode == EAudioMode.TR_AUDIOMODE_VOCALS;
+
+ if (_Pause)
+ {
+ _ArrangePauseButtons();
+ _UpdatePauseInfo();
+ _Statics[_StaticPauseVocalsIcon].X = _Texts[_TextPauseVocalsVolume].Rect.X + _PauseVocalsIconOffset;
+ }
if (pauseChanged && paused)
{
@@ -1731,8 +1835,13 @@ namespace Vocaluxe.Screens
CConfig.VocalsVolume = _SelectSlides[_SelectSlidePauseVocalsVolume].Selection * 5;
CConfig.SaveConfig();
CSound.SetStreamVolume(_CurrentStreamVocals, CConfig.VocalsVolume);
- CSound.SetPosition(_CurrentStream, _PausePosition);
- CSound.SetPosition(_CurrentStreamVocals, _PausePosition);
+ if (_PausePosition >= 0f)
+ {
+ CSound.SetPosition(_CurrentStream, _PausePosition);
+ CSound.SetPosition(_CurrentStreamVocals, _PausePosition);
+ _PausePosition = -1f;
+ }
+
// Start both streams simultaneously
CSound.Play(_CurrentStream);
CSound.Play(_CurrentStreamVocals);
@@ -1780,7 +1889,10 @@ namespace Vocaluxe.Screens
}
_Texts[_TextSongName].Text = songname;
- _Texts[_TextPauseSongName].Text = songname;
+ _Texts[_TextPauseSongName].Text = rounds > 1 ? song.Title + " (" + CGame.RoundNr + "/" + rounds + ")" : song.Title;
+ _Texts[_TextPauseArtist].Text = song.Artist;
+ _Statics[_StaticPauseCover].Texture = song.CoverTextureSmall;
+ _Statics[_StaticPauseCover].Aspect = EAspect.Crop;
if (CGame.AudioMode == EAudioMode.TR_AUDIOMODE_INSTRUMENTAL || CGame.AudioMode == EAudioMode.TR_AUDIOMODE_KARAOKE)
{
@@ -1928,6 +2040,7 @@ namespace Vocaluxe.Screens
_CurrentStreamVocals = -1;
}
+ _PausePosition = -1f;
CRecord.Stop();
if (_CurrentVideo != null)
{
@@ -2091,10 +2204,11 @@ namespace Vocaluxe.Screens
_SingNotes[_SingBars].Visible = true;
}
- _Texts[_PlayerTextName[player]].Visible = CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_BOTH ||
- CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_NAME;
- _Statics[_PlayerStaticAvatar[player]].Visible = CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_BOTH ||
- CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_AVATAR;
+ var validProfile = CProfiles.IsProfileIdValid(CGame.Players[player].ProfileId);
+ _Texts[_PlayerTextName[player]].Visible = validProfile && (CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_BOTH ||
+ CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_NAME);
+ _Statics[_PlayerStaticAvatar[player]].Visible = validProfile && (CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_BOTH ||
+ CConfig.Config.Theme.PlayerInfo == EPlayerInfo.TR_CONFIG_PLAYERINFO_AVATAR);
}
_Lyrics[_LyricMain].Alpha = 0f;
@@ -2643,7 +2757,8 @@ namespace Vocaluxe.Screens
{
if (CProfiles.IsProfileIdValid(CGame.Players[i].ProfileId))
{
- _Statics[_PlayerStaticAvatar[i]].Texture = CProfiles.GetAvatarTextureFromProfile(CGame.Players[i].ProfileId);
+ _Statics[_PlayerStaticAvatar[i]].Texture = CProfiles.GetAvatarTextureFromProfile(CGame.Players[i].ProfileId) ??
+ CBase.Themes.GetSkinTexture("NoAvatar", PartyModeId);
}
else
{
diff --git a/Vocaluxe/Screens/CScreenStatistics.cs b/Vocaluxe/Screens/CScreenStatistics.cs
index 14937a02..4b18ef42 100644
--- a/Vocaluxe/Screens/CScreenStatistics.cs
+++ b/Vocaluxe/Screens/CScreenStatistics.cs
@@ -28,7 +28,7 @@ namespace Vocaluxe.Screens
{
protected override int _ScreenVersion
{
- get { return 1; }
+ get { return 2; }
}
private const int _NumTiles = 4;
@@ -191,6 +191,11 @@ namespace Vocaluxe.Screens
selection.Y = rect.Y;
selection.W = rect.W;
selection.H = rect.H;
+
+ for (var i = 0; i < _StaticTile.Length; i++)
+ {
+ _Statics[_StaticTile[i]].Visible = i != tile;
+ }
}
private void _OpenDetail()
diff --git a/Vocaluxe/Screens/CScreenStatisticsDetail.cs b/Vocaluxe/Screens/CScreenStatisticsDetail.cs
index 2de1ef32..55cc7f48 100644
--- a/Vocaluxe/Screens/CScreenStatisticsDetail.cs
+++ b/Vocaluxe/Screens/CScreenStatisticsDetail.cs
@@ -38,7 +38,7 @@ namespace Vocaluxe.Screens
{
protected override int _ScreenVersion
{
- get { return 1; }
+ get { return 2; }
}
private sealed class CRow
@@ -76,6 +76,9 @@ namespace Vocaluxe.Screens
private float _MainColumnX;
private float _MainColumnW;
private float _ListLeft;
+ private float _FirstColumnX;
+ private float _FirstColumnW;
+ private EAlignment _FirstColumnAlign;
private readonly List _Rows = new List();
private string[] _Headers = new string[_NumColumns];
@@ -126,6 +129,9 @@ namespace Vocaluxe.Screens
_MainColumnX = _Texts[_TextCell[0, 1]].X;
_MainColumnW = _Texts[_TextCell[0, 1]].W;
_ListLeft = _Statics[_StaticRank[0]].X;
+ _FirstColumnX = _Texts[_TextCell[0, 0]].X;
+ _FirstColumnW = _Texts[_TextCell[0, 0]].W;
+ _FirstColumnAlign = _Texts[_TextCell[0, 0]].Align;
}
public override void OnShow()
@@ -405,6 +411,15 @@ namespace Vocaluxe.Screens
var mainX = string.IsNullOrEmpty(_Headers[0]) ? _ListLeft : _MainColumnX;
_Texts[_TextHeader[1]].X = mainX;
+
+ var dateColumn = Page == EStatisticsPage.Recent;
+ foreach (var text in Enumerable.Range(0, _NumRows).Select(r => _Texts[_TextCell[r, 0]]).Concat(new[] { _Texts[_TextHeader[0]] }))
+ {
+ text.Align = dateColumn ? EAlignment.Left : _FirstColumnAlign;
+ text.X = dateColumn ? _ListLeft : _FirstColumnX;
+ text.W = dateColumn ? _AvatarMainX - _ListLeft - 10 : _FirstColumnW;
+ }
+
for (var r = 0; r < _NumRows; r++)
{
_Texts[_TextCell[r, 1]].X = mainX;
diff --git a/VocaluxeLib/Menu/CNameSelection.cs b/VocaluxeLib/Menu/CNameSelection.cs
index 4e66c6d2..36d1f121 100644
--- a/VocaluxeLib/Menu/CNameSelection.cs
+++ b/VocaluxeLib/Menu/CNameSelection.cs
@@ -99,6 +99,9 @@ namespace VocaluxeLib.Menu
private readonly List _VisibleProfiles;
private readonly List _UsedProfiles;
+ private readonly HashSet _InactiveProfiles = new HashSet();
+
+ public bool ShowInactive;
private CStatic _PlayerSelector;
@@ -378,8 +381,10 @@ namespace VocaluxeLib.Menu
{
if (i + offset * _Theme.Tiles.NumW < _VisibleProfiles.Count)
{
+ var alpha = _InactiveProfiles.Contains(_VisibleProfiles[i + offset * _Theme.Tiles.NumW]) ? 0.4f : 1f;
_Tiles[i].Avatar.Texture = CBase.Profiles.GetAvatar(_VisibleProfiles[i + offset * _Theme.Tiles.NumW]);
- _Tiles[i].Avatar.Color = new SColorF(1, 1, 1, 1);
+ _Tiles[i].Avatar.Color = new SColorF(1, 1, 1, alpha);
+ _Tiles[i].Name.Alpha = alpha;
_Tiles[i].Name.Text = CBase.Profiles.GetPlayerName(_VisibleProfiles[i + offset * _Theme.Tiles.NumW]);
_Tiles[i].ProfileId = _VisibleProfiles.ElementAt(i + offset * _Theme.Tiles.NumW);
}
@@ -387,6 +392,7 @@ namespace VocaluxeLib.Menu
{
_Tiles[i].Avatar.Texture = TextureEmptyTile;
_Tiles[i].Avatar.Color = _ColorEmptyTile;
+ _Tiles[i].Name.Alpha = 1f;
_Tiles[i].Name.Text = "";
_Tiles[i].ProfileId = Guid.Empty;
}
@@ -514,11 +520,18 @@ namespace VocaluxeLib.Menu
private void _UpdateVisibleProfiles()
{
_VisibleProfiles.Clear();
+ _InactiveProfiles.Clear();
var profiles = CBase.Profiles.GetProfiles();
foreach (var profile in profiles)
{
var visible = profile.Active == EOffOn.TR_CONFIG_ON;
+ if (!visible && ShowInactive)
+ {
+ visible = true;
+ _InactiveProfiles.Add(profile.Id);
+ }
+
if (visible)
{
if (_UsedProfiles.Contains(profile.Id) && (int)profile.UserRole >= (int)EUserRole.TR_USERROLE_NORMAL)