From 61b2677f16d2fd1f6f47f61e7cac8a42719afe84 Mon Sep 17 00:00:00 2001 From: McSchneidar <262792195+McSchneidar@users.noreply.github.com> Date: Sat, 17 Oct 2026 04:23:07 +0200 Subject: [PATCH] Redesign highscore screen (#908) - Places 1-3 are shown on a podium with profile avatars and a crown for the winner - Players without an avatar get a placeholder silhouette (new skin texture NoAvatar) - Places 4-10 are listed below with a score bar for each entry - The podium only appears once there is at least one highscore - New entries are shown in gold with a slight pulse and gold sparkles --- .../Changelog/Changelog_ScreenHighscore.txt | 16 + Output/Themes/Vocaluxe 2024/01_Standard.xml | 1 + Output/Themes/Vocaluxe 2024/02.xml | 1 + Output/Themes/Vocaluxe 2024/03.xml | 1 + Output/Themes/Vocaluxe 2024/04.xml | 1 + Output/Themes/Vocaluxe 2024/05.xml | 1 + Output/Themes/Vocaluxe 2024/06.xml | 1 + Output/Themes/Vocaluxe 2024/NoAvatar.png | Bin 0 -> 3426 bytes .../Vocaluxe 2024/Screens/ScreenHighscore.xml | 863 ++++++++++++------ Vocaluxe/Screens/CScreenHighscore.cs | 273 +++--- 10 files changed, 752 insertions(+), 406 deletions(-) create mode 100644 Output/Themes/Vocaluxe 2024/NoAvatar.png diff --git a/Output/Themes/Changelog/Changelog_ScreenHighscore.txt b/Output/Themes/Changelog/Changelog_ScreenHighscore.txt index 3e9af9b1..28767616 100644 --- a/Output/Themes/Changelog/Changelog_ScreenHighscore.txt +++ b/Output/Themes/Changelog/Changelog_ScreenHighscore.txt @@ -1,5 +1,21 @@ ScreenHighscore +++++++++++ +Version 4: +(2026 Oct 15) + +Add: + (podium for places 1-3) + (avatar of the profile on the podium, skin as placeholder) + + + +Remove: +, , + +Change: +Places 1-3 are shown on the podium, places 4-10 in the list below (no scrolling). +New entries are shown in the color with a slight pulse. ++++++++++ Version 3: diff --git a/Output/Themes/Vocaluxe 2024/01_Standard.xml b/Output/Themes/Vocaluxe 2024/01_Standard.xml index da7a232c..62df8237 100644 --- a/Output/Themes/Vocaluxe 2024/01_Standard.xml +++ b/Output/Themes/Vocaluxe 2024/01_Standard.xml @@ -370,6 +370,7 @@ ToneHelper.png Score.png Star.png + NoAvatar.png SongMenu.png PauseBG.png EnergyBeam.png diff --git a/Output/Themes/Vocaluxe 2024/02.xml b/Output/Themes/Vocaluxe 2024/02.xml index ed92d714..76ada708 100644 --- a/Output/Themes/Vocaluxe 2024/02.xml +++ b/Output/Themes/Vocaluxe 2024/02.xml @@ -370,6 +370,7 @@ ToneHelper.png Score.png Star.png + NoAvatar.png SongMenu.png PauseBG.png EnergyBeam.png diff --git a/Output/Themes/Vocaluxe 2024/03.xml b/Output/Themes/Vocaluxe 2024/03.xml index fe568246..3f6ea086 100644 --- a/Output/Themes/Vocaluxe 2024/03.xml +++ b/Output/Themes/Vocaluxe 2024/03.xml @@ -370,6 +370,7 @@ ToneHelper.png Score.png Star.png + NoAvatar.png SongMenu.png PauseBG.png EnergyBeam.png diff --git a/Output/Themes/Vocaluxe 2024/04.xml b/Output/Themes/Vocaluxe 2024/04.xml index e5188c71..cd7679c1 100644 --- a/Output/Themes/Vocaluxe 2024/04.xml +++ b/Output/Themes/Vocaluxe 2024/04.xml @@ -370,6 +370,7 @@ ToneHelper.png Score.png Star.png + NoAvatar.png SongMenu.png PauseBG.png EnergyBeam.png diff --git a/Output/Themes/Vocaluxe 2024/05.xml b/Output/Themes/Vocaluxe 2024/05.xml index 09239155..fc53ee7f 100644 --- a/Output/Themes/Vocaluxe 2024/05.xml +++ b/Output/Themes/Vocaluxe 2024/05.xml @@ -370,6 +370,7 @@ ToneHelper.png Score.png Star.png + NoAvatar.png SongMenu.png PauseBG.png EnergyBeam.png diff --git a/Output/Themes/Vocaluxe 2024/06.xml b/Output/Themes/Vocaluxe 2024/06.xml index 6f39e659..99f5dca6 100644 --- a/Output/Themes/Vocaluxe 2024/06.xml +++ b/Output/Themes/Vocaluxe 2024/06.xml @@ -370,6 +370,7 @@ ToneHelper.png Score.png Star.png + NoAvatar.png SongMenu.png PauseBG.png EnergyBeam.png diff --git a/Output/Themes/Vocaluxe 2024/NoAvatar.png b/Output/Themes/Vocaluxe 2024/NoAvatar.png new file mode 100644 index 0000000000000000000000000000000000000000..966bad3db8ba669bf6f42ee8c988f922b657f046 GIT binary patch literal 3426 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 Eg3fL`-v9sr literal 0 HcmV?d00001 diff --git a/Output/Themes/Vocaluxe 2024/Screens/ScreenHighscore.xml b/Output/Themes/Vocaluxe 2024/Screens/ScreenHighscore.xml index adf7fe4d..6eac0e8a 100644 --- a/Output/Themes/Vocaluxe 2024/Screens/ScreenHighscore.xml +++ b/Output/Themes/Vocaluxe 2024/Screens/ScreenHighscore.xml @@ -2,7 +2,7 @@ ScreenHighscore - 3 + 4 @@ -25,36 +25,80 @@ 0 - + + Star + + + 940 + 133 + 40 + 40 + 0 + + + - 120 - 155 - 1620 - 52.5 - 0 + 810 + 410 + 300 + 150 + 1 - + - 120 - 245 - 1620 - 52.5 - 0 + 490 + 450 + 300 + 110 + 1 - + - 120 - 335 - 1620 - 52.5 + 1130 + 480 + 300 + 80 + 1 + + + + NoAvatar + + + 895 + 175 + 130 + 130 + 0 + + + + NoAvatar + + + 585 + 225 + 110 + 110 + 0 + + + + NoAvatar + + + 1225 + 255 + 110 + 110 0 @@ -67,7 +111,7 @@ 40.5 0 - + Left Center @@ -81,7 +125,7 @@ 40.5 0 - + Center Center @@ -95,7 +139,7 @@ 40.5 0 - + Right Center @@ -103,193 +147,193 @@ - 180 - 154.5 + 960 + 435 -2 - 52.5 + 90 0 - Right + Center Center Outline - 180 - 244.5 + 640 + 468 -2 - 52.5 + 72 0 - Right + Center Center Outline - 180 - 334.5 + 1280 + 490 -2 - 52.5 + 62 0 - Right + Center Center Outline - 180 - 424.5 - 0 - 52.5 + 185 + 596 + -2 + 46 0 - Right + Center Center Outline - 180 - 514.5 - 0 - 52.5 + 185 + 662 + -2 + 46 0 - Right + Center Center Outline - 180 - 604.5 - 0 - 52.5 + 185 + 728 + -2 + 46 0 - Right + Center Center Outline - 180 - 694.5 - 0 - 52.5 + 185 + 794 + -2 + 46 0 - Right + Center Center Outline - 180 - 784.5 - 0 - 52.5 + 185 + 860 + -2 + 46 0 - Right + Center Center Outline - 180 - 874.5 - 0 - 52.5 + 185 + 926 + -2 + 46 0 - Right + Center Center Outline - 180 - 964.5 - 0 - 52.5 + 185 + 992 + -2 + 46 0 - Right + Center Center Outline - 300 - 154.5 + 960 + 308 -2 - 52.5 - 0 + 34 + 290 - Left + Center Center Outline - 300 - 244.5 + 640 + 338 -2 - 52.5 - 0 + 34 + 290 - Left + Center Center Outline - 300 - 334.5 + 1280 + 368 -2 - 52.5 - 0 + 34 + 290 - Left + Center Center Outline - 300 - 424.5 - 0 - 52.5 - 0 + 260 + 599 + -2 + 40 + 600 Left @@ -299,11 +343,11 @@ - 300 - 514.5 - 0 - 52.5 - 0 + 260 + 665 + -2 + 40 + 600 Left @@ -313,11 +357,11 @@ - 300 - 604.5 - 0 - 52.5 - 0 + 260 + 731 + -2 + 40 + 600 Left @@ -327,11 +371,11 @@ - 300 - 694.5 - 0 - 52.5 - 0 + 260 + 797 + -2 + 40 + 600 Left @@ -341,11 +385,11 @@ - 300 - 784.5 - 0 - 52.5 - 0 + 260 + 863 + -2 + 40 + 600 Left @@ -355,11 +399,11 @@ - 300 - 874.5 - 0 - 52.5 - 0 + 260 + 929 + -2 + 40 + 600 Left @@ -369,11 +413,11 @@ - 300 - 964.5 - 0 - 52.5 - 0 + 260 + 995 + -2 + 40 + 600 Left @@ -383,434 +427,653 @@ - 1200 - 154.5 + 960 + 342 -2 - 52.5 + 34 0 - Left + Center Center Outline - 1200 - 244.5 + 640 + 372 -2 - 52.5 + 34 0 - Left + Center Center Outline - 1200 - 334.5 + 1280 + 402 -2 - 52.5 + 34 0 - Left + Center Center Outline - 1200 - 424.5 - 0 - 52.5 + 1560 + 599 + -2 + 40 0 - Left + Right Center Outline - 1200 - 514.5 - 0 - 52.5 + 1560 + 665 + -2 + 40 0 - Left + Right Center Outline - 1200 - 604.5 - 0 - 52.5 + 1560 + 731 + -2 + 40 0 - Left + Right Center Outline - 1200 - 694.5 - 0 - 52.5 + 1560 + 797 + -2 + 40 0 - Left + Right Center Outline - 1200 - 784.5 - 0 - 52.5 + 1560 + 863 + -2 + 40 0 - Left + Right Center Outline - 1200 - 874.5 - 0 - 52.5 + 1560 + 929 + -2 + 40 0 - Left + Right Center Outline - 1200 - 964.5 - 0 - 52.5 + 1560 + 995 + -2 + 40 0 - Left + Right Center Outline - 1500 - 154.5 + 960 + 376 -2 - 52.5 + 26 0 - Left + Center Center - + Outline - 1500 - 244.5 + 640 + 406 -2 - 52.5 + 26 0 - Left + Center Center - + Outline - 1500 - 334.5 + 1280 + 436 -2 - 52.5 + 26 0 - Left + Center Center - + Outline - 1500 - 424.5 - 0 - 52.5 + 1780 + 604 + -2 + 30 0 - Left + Right Center - + Outline - 1500 - 514.5 - 0 - 52.5 + 1780 + 670 + -2 + 30 0 - Left + Right Center - + Outline - 1500 - 604.5 - 0 - 52.5 + 1780 + 736 + -2 + 30 0 - Left + Right Center - + Outline - 1500 - 694.5 - 0 - 52.5 + 1780 + 802 + -2 + 30 0 - Left + Right Center - + Outline - 1500 - 784.5 - 0 - 52.5 + 1780 + 868 + -2 + 30 0 - Left + Right Center - + Outline - 1500 - 874.5 - 0 - 52.5 + 1780 + 934 + -2 + 30 0 - Left + Right Center - + Outline - 1500 - 964.5 - 0 - 52.5 + 1780 + 1000 + -2 + 30 0 - Left + Right Center - + Outline - - - - - - - - + + + PointsBarBG + + + + + + + Right + TR_CONFIG_OFF + TR_CONFIG_OFF + + + 0 + + + + + 880 + 612 + 520 + 14 + 0 + + + + PointsBarBG + + + + + + + Right + TR_CONFIG_OFF + TR_CONFIG_OFF + + + 0 + + + + + 880 + 678 + 520 + 14 + 0 + + + + PointsBarBG + + + + + + + Right + TR_CONFIG_OFF + TR_CONFIG_OFF + + + 0 + + + + + 880 + 744 + 520 + 14 + 0 + + + + PointsBarBG + + + + + + + Right + TR_CONFIG_OFF + TR_CONFIG_OFF + + + 0 + + + + + 880 + 810 + 520 + 14 + 0 + + + + PointsBarBG + + + + + + + Right + TR_CONFIG_OFF + TR_CONFIG_OFF + + + 0 + + + + + 880 + 876 + 520 + 14 + 0 + + + + PointsBarBG + + + + + + + Right + TR_CONFIG_OFF + TR_CONFIG_OFF + + + 0 + + + + + 880 + 942 + 520 + 14 + 0 + + + + PointsBarBG + + + + + + + Right + TR_CONFIG_OFF + TR_CONFIG_OFF + + + 0 + + + + + 880 + 1008 + 520 + 14 + 0 + + + Star - 120 - 150 - 1620 - 52.5 + 800 + 125 + 320 + 285 -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star - 120 - 240 - 1620 - 52.5 + 480 + 215 + 320 + 235 -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star - 120 - 330 - 1620 - 52.5 + 1120 + 245 + 320 + 235 -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star 120 - 420 - 1620 - 52.5 - 1 + 590 + 1680 + 58 + -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star 120 - 510 - 1620 - 52.5 - 1 + 656 + 1680 + 58 + -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star 120 - 600 - 1620 - 52.5 - 1 + 722 + 1680 + 58 + -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star 120 - 690 - 1620 - 52.5 - 1 + 788 + 1680 + 58 + -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star 120 - 780 - 1620 - 52.5 - 1 + 854 + 1680 + 58 + -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star 120 - 870 - 1620 - 52.5 - 1 + 920 + 1680 + 58 + -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 Star 120 - 960 - 1620 - 52.5 - 1 + 986 + 1680 + 58 + -1 - + + 1 + 0.8 + 0 + 0.6 + Star - 25 - 100 + 18 + 40 diff --git a/Vocaluxe/Screens/CScreenHighscore.cs b/Vocaluxe/Screens/CScreenHighscore.cs index 4c274303..342ec36c 100644 --- a/Vocaluxe/Screens/CScreenHighscore.cs +++ b/Vocaluxe/Screens/CScreenHighscore.cs @@ -17,10 +17,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Windows.Forms; using Vocaluxe.Base; using VocaluxeLib; +using VocaluxeLib.Draw; using VocaluxeLib.Menu; using VocaluxeLib.Songs; @@ -31,22 +33,28 @@ 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 3; } + get { return 4; } } private const int _NumEntrys = 10; + private const int _NumPodium = 3; + private const int _NumRows = _NumEntrys - _NumPodium; private const string _TextSongName = "TextSongName"; private const string _TextSongMode = "TextSongMode"; + private const string _StaticCrown = "StaticCrown"; private string[] _TextNumber; private string[] _TextName; private string[] _TextScore; private string[] _TextDate; private string[] _ParticleEffectNew; + private string[] _StaticPodium; + private string[] _StaticAvatar; + private string[] _ProgressBarScore; + private CTextureRef[] _PodiumAvatars; private List[] _Scores; private List _NewEntryIds; private int _Round; - private int _Pos; private bool _IsDuet; private bool _FromScreenSong = false; @@ -58,6 +66,17 @@ namespace Vocaluxe.Screens private int _HighscoreStream = -1; private bool _HasPlayedHighscoreSound = false; + private struct STextStyle + { + public float Height; + public float Y; + public SColorF Color; + } + + private readonly Dictionary _TextStyles = new Dictionary(); + private readonly Stopwatch _PulseTimer = new Stopwatch(); + private SColorF _NewEntryColor; + private static int PlaySound(ESounds sound, int volume) { var streamId = CSound.PlaySound(sound, false); @@ -106,13 +125,56 @@ namespace Vocaluxe.Screens _ParticleEffectNew[i] = "ParticleEffectNew" + (i + 1); } - _ThemeStatics = new string[] { "StaticTop1Bar", "StaticTop2Bar", "StaticTop3Bar" }; + var statics = new List { _StaticCrown }; + + _StaticPodium = new string[_NumPodium]; + _StaticAvatar = new string[_NumPodium]; + for (var i = 0; i < _NumPodium; i++) + { + _StaticPodium[i] = "StaticPodium" + (i + 1); + _StaticAvatar[i] = "StaticAvatar" + (i + 1); + statics.Add(_StaticPodium[i]); + statics.Add(_StaticAvatar[i]); + } + + _ProgressBarScore = new string[_NumRows]; + for (var i = 0; i < _NumRows; i++) + { + _ProgressBarScore[i] = "ProgressBarScore" + (i + _NumPodium + 1); + } + + _ThemeStatics = statics.ToArray(); _ThemeTexts = texts.ToArray(); _ThemeParticleEffects = _ParticleEffectNew; + _ThemeProgressBars = _ProgressBarScore; + _PodiumAvatars = new CTextureRef[_NumPodium]; _NewEntryIds = new List(); } + public override void LoadTheme(string xmlPath) + { + base.LoadTheme(xmlPath); + + foreach (var avatar in _StaticAvatar) + { + _Statics[avatar].Aspect = EAspect.Crop; + } + + _TextStyles.Clear(); + foreach (var name in _TextNumber.Concat(_TextName).Concat(_TextScore).Concat(_TextDate)) + { + _TextStyles[name] = new STextStyle { Height = _Texts[name].Font.Height, Y = _Texts[name].Y, Color = _Texts[name].Color }; + } + + if (!CBase.Themes.GetColor("Top1Color", PartyModeId, out _NewEntryColor)) + { + _NewEntryColor = new SColorF(1f, 0.8f, 0f, 1f); + } + + _NewEntryColor.A = 1f; + } + public override bool HandleInput(SKeyEvent keyEvent) { if (keyEvent.KeyPressed && !Char.IsControl(keyEvent.Unicode)) { } @@ -126,22 +188,6 @@ namespace Vocaluxe.Screens _LeaveScreen(); break; - case Keys.Down: - if (!_FromScreenSong) - { - _ChangePos(1); - } - - break; - - case Keys.Up: - if (!_FromScreenSong) - { - _ChangePos(-1); - } - - break; - case Keys.Left: _ChangeRound(-1); break; @@ -180,87 +226,93 @@ namespace Vocaluxe.Screens } } - _ChangePos(mouseEvent.Wheel); return true; } public override bool UpdateGame() { var numScores = _Scores[_Round].Count; - _Statics["StaticTop1Bar"].Visible = numScores >= 1; - _Statics["StaticTop2Bar"].Visible = numScores >= 2; - _Statics["StaticTop3Bar"].Visible = numScores >= 3; + _Statics[_StaticCrown].Visible = numScores > 0; + foreach (var podium in _StaticPodium) + { + _Statics[podium].Visible = numScores > 0; + } for (var p = 0; p < _NumEntrys; p++) { - if (_Pos + p < _Scores[_Round].Count) + var isEntry = p < numScores; + var isNew = isEntry && _IsNewEntry(_Scores[_Round][p].Id); + + _Texts[_TextNumber[p]].Visible = isEntry || (p < _NumPodium && numScores > 0); + _Texts[_TextName[p]].Visible = isEntry; + _Texts[_TextScore[p]].Visible = isEntry; + _Texts[_TextDate[p]].Visible = isEntry; + _ParticleEffects[_ParticleEffectNew[p]].Visible = isNew; + _SetNewEntryStyle(p, isNew); + + _Texts[_TextNumber[p]].Text = (p + 1).ToString(); + + if (p < _NumPodium) { - _Texts[_TextNumber[p]].Visible = true; - _Texts[_TextName[p]].Visible = true; - _Texts[_TextScore[p]].Visible = true; - _Texts[_TextDate[p]].Visible = true; - - _Texts[_TextNumber[p]].Text = (_Pos + p + 1).ToString(); - - var name = _Scores[_Round][_Pos + p].Name; - name += " [" + CLanguage.Translate(Enum.GetName(typeof(EGameDifficulty), _Scores[_Round][_Pos + p].Difficulty)) + "]"; - if (_IsDuet) - { - var voiceNr = _Scores[_Round][_Pos + p].VoiceNr; - string voiceName = null; - - CSong song; - if (_FromScreenSong) - { - song = CSongs.GetSong(CScreenSong.getSelectedSongId()); - } - else - { - song = CGame.GetSong(_Round); - } - - if (song != null && song.Notes != null && song.Notes.VoiceNames != null) - { - try - { - voiceName = song.Notes.VoiceNames[voiceNr]; - } - catch - { - voiceName = null; // Ungültiger Index - } - } - - if (!string.IsNullOrWhiteSpace(voiceName)) - { - name += " (" + voiceName + ")"; - } - else - { - name += " (P" + (voiceNr + 1) + ")"; - } - } - - _Texts[_TextName[p]].Text = name; - - _Texts[_TextScore[p]].Text = _Scores[_Round][_Pos + p].Score.ToString("D"); - _Texts[_TextDate[p]].Text = _Scores[_Round][_Pos + p].Date; - - _ParticleEffects[_ParticleEffectNew[p]].Visible = _IsNewEntry(_Scores[_Round][_Pos + p].Id); - - if (_ParticleEffects[_ParticleEffectNew[p]].Visible && !_HasPlayedHighscoreSound) - { - _HighscoreStream = CScreenHighscore.PlaySound(ESounds.Highscore, CConfig.SoundEffectVolume); - _HasPlayedHighscoreSound = true; - } + _Statics[_StaticAvatar[p]].Texture = _PodiumAvatars[p]; + _Statics[_StaticAvatar[p]].Visible = isEntry && _Statics[_StaticAvatar[p]].Texture != null; } else { - _Texts[_TextNumber[p]].Visible = false; - _Texts[_TextName[p]].Visible = false; - _Texts[_TextScore[p]].Visible = false; - _Texts[_TextDate[p]].Visible = false; - _ParticleEffects[_ParticleEffectNew[p]].Visible = false; + var row = p - _NumPodium; + _ProgressBars[_ProgressBarScore[row]].Visible = isEntry; + + var progress = isEntry ? (float)_Scores[_Round][p].Score / CSettings.MaxScore : 0f; + if (_ProgressBars[_ProgressBarScore[row]].Progress != progress) + { + _ProgressBars[_ProgressBarScore[row]].Progress = progress; + } + } + + if (!isEntry) + { + continue; + } + + var name = _Scores[_Round][p].Name; + name += " [" + CLanguage.Translate(Enum.GetName(typeof(EGameDifficulty), _Scores[_Round][p].Difficulty)) + "]"; + if (_IsDuet) + { + var voiceNr = _Scores[_Round][p].VoiceNr; + string voiceName = null; + + var song = _GetCurrentSong(); + if (song != null && song.Notes != null && song.Notes.VoiceNames != null) + { + try + { + voiceName = song.Notes.VoiceNames[voiceNr]; + } + catch + { + voiceName = null; // Ungültiger Index + } + } + + if (!string.IsNullOrWhiteSpace(voiceName)) + { + name += " (" + voiceName + ")"; + } + else + { + name += " (P" + (voiceNr + 1) + ")"; + } + } + + _Texts[_TextName[p]].Text = name; + + _Texts[_TextScore[p]].Text = _Scores[_Round][p].Score.ToString("D"); + _Texts[_TextDate[p]].Text = _Scores[_Round][p].Date; + + if (isNew && !_HasPlayedHighscoreSound) + { + _HighscoreStream = CScreenHighscore.PlaySound(ESounds.Highscore, CConfig.SoundEffectVolume); + _HasPlayedHighscoreSound = true; } } @@ -271,8 +323,8 @@ namespace Vocaluxe.Screens { base.OnShow(); _HasPlayedHighscoreSound = false; + _PulseTimer.Restart(); _Round = 0; - _Pos = 0; _NewEntryIds.Clear(); _AddScoresToDB(); _LoadScores(); @@ -281,6 +333,19 @@ namespace Vocaluxe.Screens UpdateGame(); } + private void _SetNewEntryStyle(int entry, bool isNew) + { + var scale = isNew ? 1f + 0.03f * (float)Math.Sin(_PulseTimer.ElapsedMilliseconds / 1000.0 * Math.PI * 1.4) : 1f; + foreach (var name in new[] { _TextNumber[entry], _TextName[entry], _TextScore[entry], _TextDate[entry] }) + { + var style = _TextStyles[name]; + var text = _Texts[name]; + text.Color = isNew ? _NewEntryColor : style.Color; + text.Font.Height = style.Height * scale; + text.Y = style.Y - style.Height * (scale - 1f) / 2f; + } + } + private bool _IsNewEntry(int id) { return _NewEntryIds.Any(t => t == id); @@ -316,7 +381,6 @@ namespace Vocaluxe.Screens private void _LoadScores() { - _Pos = 0; var rounds = CGame.NumRounds; if (rounds == 0) @@ -357,16 +421,12 @@ namespace Vocaluxe.Screens _IsDuet = false; var points = CGame.GetPoints(); - CSong song; - if (_FromScreenSong) + for (var p = 0; p < _NumPodium; p++) { - song = CSongs.GetSong(CScreenSong.getSelectedSongId()); - } - else - { - song = CGame.GetSong(_Round); + _PodiumAvatars[p] = p < _Scores[_Round].Count ? _GetAvatarTexture(_Scores[_Round][p].Name) : null; } + var song = _GetCurrentSong(); if (song == null) { return; @@ -401,21 +461,22 @@ namespace Vocaluxe.Screens _Texts[_TextSongMode].Text = "TR_GAMEMODE_NORMAL"; break; } - - _Pos = 0; } - private void _ChangePos(int num) + private CSong _GetCurrentSong() { - if (_Scores[_Round].Count == 0 || _Scores[_Round].Count <= _NumEntrys) + if (_FromScreenSong) { - _Pos = 0; - } - else - { - _Pos += num; - _Pos = _Pos.Clamp(0, _Scores[_Round].Count - 1, true); + return CSongs.GetSong(CScreenSong.getSelectedSongId()); } + + return CGame.GetSong(_Round); + } + + private static CTextureRef _GetAvatarTexture(string playerName) + { + var profile = CProfiles.GetProfiles().FirstOrDefault(pr => pr.PlayerName == playerName && pr.Avatar != null); + return profile == null ? null : profile.Avatar.Texture; } private void _ChangeRound(int num)