diff --git a/Output/Cover/Genius Standard.xml b/Output/Cover/01_Genius Standard.xml similarity index 100% rename from Output/Cover/Genius Standard.xml rename to Output/Cover/01_Genius Standard.xml diff --git a/Output/Cover/02_Genius Blue.xml b/Output/Cover/02_Genius Blue.xml new file mode 100644 index 00000000..4d51eb2b --- /dev/null +++ b/Output/Cover/02_Genius Blue.xml @@ -0,0 +1,166 @@ + + + + Genius Blue + Genius + Jiiniasu + + + + + + + %TEXT% + + Normal + + + + 550 + + + + + 0.855 + 0.937 + 0.945 + 0.8 + + + + 24 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + + + + %TEXT% + + Normal + + + + 550 + + + + + 0.855 + 0.937 + 0.945 + 0.8 + + + + -150 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + + + + %TEXT% + + Normal + + + + 550 + + + + + 0.855 + 0.937 + 0.945 + 0.8 + + + + 150 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + + + + %TEXT% + + Normal + + + + 120 + + + + + 0.855 + 0.937 + 0.945 + 0.8 + + + + -150 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + diff --git a/Output/Cover/03_Genius Red.xml b/Output/Cover/03_Genius Red.xml new file mode 100644 index 00000000..26c2c8ae --- /dev/null +++ b/Output/Cover/03_Genius Red.xml @@ -0,0 +1,166 @@ + + + + Genius Red + Genius + Jiiniasu + + + + + + + %TEXT% + + Normal + + + + 550 + + + + + 0.988 + 0.682 + 0.733 + 0.8 + + + + 24 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + + + + %TEXT% + + Normal + + + + 550 + + + + + 0.988 + 0.682 + 0.733 + 0.8 + + + + -150 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + + + + %TEXT% + + Normal + + + + 550 + + + + + 0.988 + 0.682 + 0.733 + 0.8 + + + + 150 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + + + + %TEXT% + + Normal + + + + 120 + + + + + 0.988 + 0.682 + 0.733 + 0.8 + + + + -150 + + + 100 + + + 1 + 1 + 1 + 1 + + + Cover.png + + 1.0 + + True + + diff --git a/Output/Languages/English.xml b/Output/Languages/English.xml index 63a4bad3..fc7a4ca2 100644 --- a/Output/Languages/English.xml +++ b/Output/Languages/English.xml @@ -152,6 +152,10 @@ (%v songs) (%v song) %a - %t + A-Z = Jump to the letter • F3 = Search • CTRL+R = Random selection • CTRL+S = Start medley • CTRL+# = Change song sorting • CTRL+T = Enable/Disable category view • Space = Open song options • ESC = Back to main menu + A-Z = Search artist and title, prefixes for the search → a: = artist • t: = title • c: = creator • e: = edition • g: = genre • y: = year (e.g. 1999 or 1980-1989) • l: = language • al: = album • fi: = file name • fo: = folder name + 1-6 = Press your team number to use a random song joker + Sorting: %s Pause Stop singing Continue diff --git a/Output/Languages/German.xml b/Output/Languages/German.xml index 1de7ea61..dc0fc2d1 100644 --- a/Output/Languages/German.xml +++ b/Output/Languages/German.xml @@ -147,6 +147,10 @@ (%v Lieder) (%v Lied) %a -%t + A-Z = Zum Buchstaben springen • F3 = Suchen • STRG+R = Zufällige Auswahl • STRG+S = Starte Medley • STRG+# = Song Sortierung ändern • STRG+T = Kategorieansicht ein-/ausschalten • Leertaste = Lied-Optionen öffnen • ESC = Zurück zum Hauptmenü + A-Z = Interpreten und Titel durchsuchen, Präfixe für die Suche → a: = Interpret • t: = Titel • c: = Ersteller • e: = Edition • g: = Genre • y: = Jahr (z.B. 1999 oder 1980-1989) • l: = Sprache • al: = Album • fi: = Dateiname • fo: = Ordnername + 1-6 = Drücke die Teamnummer um einen Zufallssong Joker zu verwenden + Sortierung: %s Pause Lied beenden Fortfahren diff --git a/Output/Readme.txt b/Output/Readme.txt index 13d36037..cf86550d 100644 --- a/Output/Readme.txt +++ b/Output/Readme.txt @@ -132,12 +132,17 @@ Song screen [F3] to open/close the song search menu [SPACE] to open/close the song menu [TAB] to switch selection of song menu and playlist (if opened) +[CTRL] + [H] to show the highscore of the selected song +[CTRL] + [T] to toggle category / tabs view +[CTRL] + [1]..[0] to change the song sorting (just changed for runtime, not saved!), in order from keys 1 to 0: + folder, artist, artist by letter, title by letter, edition, genre, language, year, decade, date added [CTRL] + [R] to select a random song [CTRL] + [A] to sing all songs [CTRL] + [S] to sing current song in medley version [CTRL] + [V] to sing all songs from a category [NUM_1]..[NUM_6] to use a Joker for team 1..6 -[A]..[Z] to jump to category/song title starting with that letter +[A]..[Z] to jump to category/song title starting with that letters (multiple letters possible) +[PAGE UP] or [PAGE DOWN] if inside a category: Go up/down one category / if category view is disabled: Scroll one page up/down Name selection screen [1]..[6] to activate player selection. @@ -149,6 +154,7 @@ Name selection screen Sing screen [P] to toggle pause. [CTRL] + [S] to skip a song if there is another one in the playlist. +[CTRL] + [RIGHT] to skip 30 seconds within the playing song (not in party modes). [T] to change the time format of the timer. [I] to change view of player information. [W] to activate the configured webcam. @@ -156,6 +162,7 @@ Sing screen Score and highscore screen [LEFT] or [RIGHT] to show (high)scores of another round (if there is more than one) + if opened from song list screen: Switch between game modes (Normal, Medley, Duet, Short) ================================= diff --git a/Output/Themes/Changelog/Changelog_ScreenSong.txt b/Output/Themes/Changelog/Changelog_ScreenSong.txt index 4b71ef3c..89d4820b 100644 --- a/Output/Themes/Changelog/Changelog_ScreenSong.txt +++ b/Output/Themes/Changelog/Changelog_ScreenSong.txt @@ -1,5 +1,14 @@ ScreenSong +++++++++++ +Version 7: + +Add: + + + +Shows key shortcut and search usage as small text line at the bottom of the screen. + ++++++++++ Version 6: @@ -43,4 +52,4 @@ to SongMenu Add: and to SongMenu.SongMenuTileBoard -++++++++++ \ No newline at end of file +++++++++++ diff --git a/Output/Themes/Genius/Screens/ScreenSing.xml b/Output/Themes/Genius/Screens/ScreenSing.xml index 821093fb..36cebdac 100644 --- a/Output/Themes/Genius/Screens/ScreenSing.xml +++ b/Output/Themes/Genius/Screens/ScreenSing.xml @@ -46,7 +46,7 @@ 0 - 0 + 610 1280 90 -0.75 @@ -136,7 +136,7 @@ 40 - 10 + 623 45 36 -1 @@ -1501,7 +1501,7 @@ 637 - 7 + 620 1200 42 -1 @@ -1512,7 +1512,7 @@ 637 - 48 + 662 1200 35 -1 diff --git a/Output/Themes/Genius/Screens/ScreenSong.xml b/Output/Themes/Genius/Screens/ScreenSong.xml index 1b74ad72..f5abfa40 100644 --- a/Output/Themes/Genius/Screens/ScreenSong.xml +++ b/Output/Themes/Genius/Screens/ScreenSong.xml @@ -2,7 +2,7 @@ ScreenSong - 6 + 8 @@ -70,8 +70,33 @@ -2.1 + + + + + 490 + 0 + 300 + 30 + -0.75 + + + + 640 + 2 + -1 + 25 + 280 + + + Center + Center + + Outline + TR_SCREENSONG_SORTING + 950 65 @@ -238,6 +263,48 @@ Outline TR_SCREENSONG_SONGOPTIONS + + 40 + 700 + 0 + 16 + 1200 + + + Left + Bottom + + Outline + TR_SCREENSONG_HELPMESSAGE + + + 40 + 700 + 0 + 16 + 1200 + + + Left + Bottom + + Outline + TR_SCREENSONG_HELPMESSAGESEARCH + + + 40 + 700 + 0 + 16 + 1200 + + + Left + Bottom + + Outline + TR_SCREENSONG_HELPMESSAGEPARTY + + diff --git a/PartyModes/PartyModeChallenge/CPartyModeChallenge.cs b/PartyModes/PartyModeChallenge/CPartyModeChallenge.cs index 46260e8c..da556692 100644 --- a/PartyModes/PartyModeChallenge/CPartyModeChallenge.cs +++ b/PartyModes/PartyModeChallenge/CPartyModeChallenge.cs @@ -427,6 +427,7 @@ namespace VocaluxeLib.PartyModes.Challenge _ScreenSongOptions.Sorting.Tabs = CBase.Config.GetTabs(); _ScreenSongOptions.Sorting.FilterPlaylistID = -1; + _ScreenSongOptions.Selection.SongIndex = -1; _ScreenSongOptions.Selection.CategoryIndex = -1; _ScreenSongOptions.Selection.CategoryChangeAllowed = true; break; @@ -718,4 +719,4 @@ namespace VocaluxeLib.PartyModes.Challenge return result; } } -} \ No newline at end of file +} diff --git a/Tests/VocaluxeLib/Log/CLogTest.cs b/Tests/VocaluxeLib/Log/CLogTest.cs index 56ddf159..48eb5b84 100644 --- a/Tests/VocaluxeLib/Log/CLogTest.cs +++ b/Tests/VocaluxeLib/Log/CLogTest.cs @@ -76,7 +76,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Verbose] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -129,7 +129,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Verbose] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -287,7 +287,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Debug] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -340,7 +340,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Debug] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -498,7 +498,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Information] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -551,7 +551,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Information] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -709,7 +709,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Warning] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -762,7 +762,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Warning] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -920,7 +920,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Error] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); @@ -973,7 +973,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[Error] " + _TestMessageWithResolvedData, log, "Main log entry wrong"); - StringAssert.Contains(_TestMessageWithData, error, "Error message wrong"); + StringAssert.Contains(_TestMessageWithResolvedData, error, "Error message wrong"); }, ELogLevel.Verbose); diff --git a/Tests/VocaluxeLib/Log/CLogTest.tt b/Tests/VocaluxeLib/Log/CLogTest.tt index fac62cfb..1ca560dd 100644 --- a/Tests/VocaluxeLib/Log/CLogTest.tt +++ b/Tests/VocaluxeLib/Log/CLogTest.tt @@ -101,7 +101,7 @@ namespace Tests.VocaluxeLib.Log StringAssert.Contains("Version = " + versionTag, log, "Main log version tag entry wrong"); StringAssert.Contains("[<#= LogLevel #>] " + <#= WithData?"_TestMessageWithResolvedData":"_TestMessage" #>, log, "Main log entry wrong"); - StringAssert.Contains(<#= WithData?"_TestMessageWithData":"_TestMessage" #>, error, "Error message wrong"); + StringAssert.Contains(<#= WithData?"_TestMessageWithResolvedData":"_TestMessage" #>, error, "Error message wrong"); }, ELogLevel.Verbose); diff --git a/Vocaluxe/Base/CBackgroundMusic.cs b/Vocaluxe/Base/CBackgroundMusic.cs index 5050b408..44295ce2 100644 --- a/Vocaluxe/Base/CBackgroundMusic.cs +++ b/Vocaluxe/Base/CBackgroundMusic.cs @@ -316,56 +316,33 @@ namespace Vocaluxe.Base CSound.SetGlobalVolume(CConfig.PreviewMusicVolume); } + //Change song position only if song is changed or near to end bool songChanged = _CurPlayer.SongID != song.ID; + if (!songChanged && _CurPlayer.Position + 30 < _CurPlayer.Length) + return; _PreviewPlayer.Load(song); - - //Change song position only if song is changed or near to end - if (songChanged || _CurPlayer.Position + 30 < _CurPlayer.Length || _PreviewStartHelperTask == null) + lock (_PreviewStartHelperTaskLock) { - lock (_PreviewStartHelperTaskLock) + _PreviewStartHelperTask = new Task(() => { - _PreviewStartHelperTask = new Task(() => - { - float length = _PreviewPlayer.Length; - if (length < 1) - length = 30; // If length is unknow or invalid assume a length of 30s + float length = _PreviewPlayer.Length; + if (length < 1) + length = 30; // If length is unknow or invalid assume a length of 30s - if (start < 0) - start = (song.Preview.Source == EDataSource.None) ? length / 4f : song.Preview.StartTime; - if (start > length - 5f) - start = Math.Max(0f, Math.Min(length / 4f, length - 5f)); - if (start >= 0.5f) - start -= 0.5f; + if (start < 0) + start = (song.Preview.Source == EDataSource.None) ? length / 4f : song.Preview.StartTime; + if (start > length - 5f) + start = Math.Max(0f, Math.Min(length / 4f, length - 5f)); + if (start >= 0.5f) + start -= 0.5f; - _PreviewPlayer.Position = start; - Play(); - }); - } - _CurPlayer = _PreviewPlayer; + _PreviewPlayer.Position = start; + Play(); + }); } - else - { - if (_PreviewStartHelperTask != null) - { - lock (_PreviewStartHelperTaskLock) - { - // Recheck the condition as it cloud have change before we got the lock - if (_PreviewStartHelperTask != null) - { - _PreviewStartHelperTask = null; - } - } - } - _PreviewPlayer.Position = _CurPlayer.Position; - _CurPlayer = _PreviewPlayer; - Play(); - } - - - - + _CurPlayer = _PreviewPlayer; } public static void StopPreview() @@ -460,4 +437,4 @@ namespace Vocaluxe.Base return _BGMusicFiles.Contains(element); } } -} \ No newline at end of file +} diff --git a/Vocaluxe/Base/CCover.cs b/Vocaluxe/Base/CCover.cs index 3ac5a87b..f464d6d9 100644 --- a/Vocaluxe/Base/CCover.cs +++ b/Vocaluxe/Base/CCover.cs @@ -133,6 +133,11 @@ namespace Vocaluxe.Base { _UnloadCovers(); _LoadCovers(); + + // Stefan1200: Added a workaround to fix issue #446, because switching the cover theme gets bugged on the song screen and needed a game restart. + // Toggle the tabs view fixes this bug somehow. + CSongs.Categorizer.Tabs = (CConfig.Config.Game.Tabs == EOffOn.TR_CONFIG_ON ? EOffOn.TR_CONFIG_OFF : EOffOn.TR_CONFIG_ON); + CSongs.Categorizer.Tabs = CConfig.Config.Game.Tabs; } private static void _UnloadCovers() @@ -288,4 +293,4 @@ namespace Vocaluxe.Base } } } -} \ No newline at end of file +} diff --git a/Vocaluxe/Base/CSongFilter.cs b/Vocaluxe/Base/CSongFilter.cs index 20596803..6d9870e6 100644 --- a/Vocaluxe/Base/CSongFilter.cs +++ b/Vocaluxe/Base/CSongFilter.cs @@ -1,4 +1,4 @@ -#region license +#region license // This file is part of Vocaluxe. // // Vocaluxe is free software: you can redistribute it and/or modify @@ -93,6 +93,89 @@ namespace Vocaluxe.Base if (_SearchString != "") searchStrings = _SearchString.ToUpper().Split(new char[] {' '}); + String searchForArtist = null; // a: + String searchForTitle = null; // t: + String searchForGenre = null; // g: + String searchForYear = null; // y: + String searchForLanguage = null; // l: + String searchForCreator = null; // c: + String searchForEdition = null; // e: + String searchForAlbum = null; // al: + String searchForFileName = null; // fi: + String searchForFolderName = null; // fo: + bool expertSearch = false; + + if (searchStrings != null) + { + foreach (String searchToken in searchStrings) + { + if (searchToken.Length < 3) + continue; + + String temp = searchToken.Substring(0, 2); + bool foundIt = true; + + switch (temp) + { + case "A:": + searchForArtist = searchToken.Substring(2); + break; + case "T:": + searchForTitle = searchToken.Substring(2); + break; + case "G:": + searchForGenre = searchToken.Substring(2); + break; + case "Y:": + searchForYear = searchToken.Substring(2); + break; + case "L:": + searchForLanguage = searchToken.Substring(2); + break; + case "C:": + searchForCreator = searchToken.Substring(2); + break; + case "E:": + searchForEdition = searchToken.Substring(2); + break; + default: + foundIt = false; + break; + } + + if (foundIt) + { + if (!expertSearch) expertSearch = true; + continue; + } + + if (searchToken.Length < 4) + continue; + + foundIt = true; + temp = searchToken.Substring(0, 3); + + switch (temp) + { + case "AL:": + searchForAlbum = searchToken.Substring(3); + break; + case "FI:": + searchForFileName = searchToken.Substring(3); + break; + case "FO:": + searchForFolderName = searchToken.Substring(3); + break; + default: + foundIt = false; + break; + } + + if (foundIt && !expertSearch) + expertSearch = true; + } + } + foreach (CSong song in CSongs.Songs) { if (_PlaylistID != -1 && !CBase.Playlist.ContainsSong(_PlaylistID, song.ID)) @@ -102,9 +185,85 @@ namespace Vocaluxe.Base { if (searchStrings == null) _FilteredSongs.Add(song); + else if (expertSearch) + { + // Stefan1200: Stop at a maximum of 500 search result to prevent performance issues + if (_FilteredSongs.Count >= 500) + break; + + if (searchForAlbum != null && song.Album.ToUpper().Contains(searchForAlbum)) + _FilteredSongs.Add(song); + if (searchForArtist != null && song.Artist.ToUpper().Contains(searchForArtist)) + _FilteredSongs.Add(song); + if (searchForTitle != null && song.Title.ToUpper().Contains(searchForTitle)) + _FilteredSongs.Add(song); + if (searchForCreator != null && song.Creator.ToUpper().Contains(searchForCreator)) + _FilteredSongs.Add(song); + if (searchForFileName != null && song.FileName.ToUpper().Contains(searchForFileName)) + _FilteredSongs.Add(song); + if (searchForFolderName != null && song.FolderName.ToUpper().Contains(searchForFolderName)) + _FilteredSongs.Add(song); + + if (searchForGenre != null) + { + foreach (String genre in song.Genres) + { + if (genre.ToUpper().Contains(searchForGenre)) + _FilteredSongs.Add(song); + } + } + + if (searchForLanguage != null) + { + foreach (String language in song.Languages) + { + if (language.ToUpper().Contains(searchForLanguage)) + _FilteredSongs.Add(song); + } + } + + if (searchForEdition != null) + { + foreach (String edition in song.Editions) + { + if (edition.ToUpper().Contains(searchForEdition)) + _FilteredSongs.Add(song); + } + } + + if (searchForYear != null) + { + int pos = searchForYear.IndexOf("-"); + if (pos == -1) + { + if (song.Year.Contains(searchForYear)) + _FilteredSongs.Add(song); + } + else if (searchForYear.Length == 9) + { + int yearStart = -1; + int yearEnd = -1; + if (!Int32.TryParse(searchForYear.Substring(0, pos), out yearStart)) + continue; + if (!Int32.TryParse(searchForYear.Substring(pos + 1), out yearEnd)) + continue; + + // Stefan1200: Prevent searches like 0000-9999, limit for a max distance of 100 years + if (yearEnd - yearStart > 100) + continue; + + int yearSearch = -1; + if (!Int32.TryParse(song.Year, out yearSearch)) + continue; + + if (yearSearch >= yearStart && yearSearch <= yearEnd) + _FilteredSongs.Add(song); + } + } + } else { - string search = song.Title.ToUpper() + " " + song.Artist.ToUpper() + " " + song.FolderName.ToUpper() + " " + song.FileName.ToUpper(); + string search = song.Title.ToUpper() + " " + song.Artist.ToUpper(); if (searchStrings.All(search.Contains)) _FilteredSongs.Add(song); @@ -114,4 +273,4 @@ namespace Vocaluxe.Base _Changed = false; } } -} \ No newline at end of file +} diff --git a/Vocaluxe/Base/CSongSorter.cs b/Vocaluxe/Base/CSongSorter.cs index 8a956107..318ba811 100644 --- a/Vocaluxe/Base/CSongSorter.cs +++ b/Vocaluxe/Base/CSongSorter.cs @@ -181,8 +181,12 @@ namespace Vocaluxe.Base sortList.Sort(_SortByFieldArtistTitle); break; } + + if (_SongSorting == ESongSorting.TR_CONFIG_DATEADDED) + sortList.Reverse(); + _SortedSongs = sortList.ToArray(); _Changed = false; } } -} \ No newline at end of file +} diff --git a/Vocaluxe/Screens/CScreenHighscore.cs b/Vocaluxe/Screens/CScreenHighscore.cs index 0e6a746f..19769991 100644 --- a/Vocaluxe/Screens/CScreenHighscore.cs +++ b/Vocaluxe/Screens/CScreenHighscore.cs @@ -49,6 +49,7 @@ namespace Vocaluxe.Screens private int _Round; private int _Pos; private bool _IsDuet; + private bool _FromScreenSong = false; public override EMusicType CurrentMusicType { @@ -113,11 +114,13 @@ namespace Vocaluxe.Screens break; case Keys.Down: - _ChangePos(1); + if (!_FromScreenSong) + _ChangePos(1); break; case Keys.Up: - _ChangePos(-1); + if (!_FromScreenSong) + _ChangePos(-1); break; case Keys.Left: @@ -234,13 +237,37 @@ namespace Vocaluxe.Screens { _Pos = 0; int rounds = CGame.NumRounds; - _Scores = new List[rounds]; - for (int round = 0; round < rounds; round++) + + if (rounds == 0) { - int songID = CGame.GetSong(round).ID; - EGameMode gameMode = CGame.GetGameMode(round); + _FromScreenSong = true; + _Round = (int)EGameMode.TR_GAMEMODE_NORMAL; + _Scores = new List[4]; + int songID = CScreenSong.getSelectedSongID(); EHighscoreStyle style = CBase.Config.GetHighscoreStyle(); - _Scores[round] = CDataBase.LoadScore(songID, gameMode, style); + bool foundHighscoreEntries = false; + + for (int gameModeNum = 0; gameModeNum < 4; gameModeNum++) + { + _Scores[gameModeNum] = CDataBase.LoadScore(songID, (EGameMode)gameModeNum, style); + if (!foundHighscoreEntries && _Scores[gameModeNum].Count > 0) + { + _Round = gameModeNum; + foundHighscoreEntries = true; + } + } + } + else + { + _FromScreenSong = false; + _Scores = new List[rounds]; + for (int round = 0; round < rounds; round++) + { + int songID = CGame.GetSong(round).ID; + EGameMode gameMode = CGame.GetGameMode(round); + EHighscoreStyle style = CBase.Config.GetHighscoreStyle(); + _Scores[round] = CDataBase.LoadScore(songID, gameMode, style); + } } } @@ -248,15 +275,21 @@ namespace Vocaluxe.Screens { _IsDuet = false; CPoints points = CGame.GetPoints(); - CSong song = CGame.GetSong(_Round); + + CSong song; + if (_FromScreenSong) + song = CSongs.GetSong(CScreenSong.getSelectedSongID()); + else + song = CGame.GetSong(_Round); + if (song == null) return; _Texts[_TextSongName].Text = song.Artist + " - " + song.Title; - if (points.NumRounds > 1) + if (points != null && !_FromScreenSong && points.NumRounds > 1) _Texts[_TextSongName].Text += " (" + (_Round + 1) + "/" + points.NumRounds + ")"; - switch (CGame.GetGameMode(_Round)) + switch ((_FromScreenSong ? (EGameMode)_Round : CGame.GetGameMode(_Round))) { case EGameMode.TR_GAMEMODE_NORMAL: _Texts[_TextSongMode].Text = "TR_GAMEMODE_NORMAL"; @@ -296,9 +329,20 @@ namespace Vocaluxe.Screens private void _ChangeRound(int num) { - CPoints points = CGame.GetPoints(); - _Round += num; - _Round = _Round.Clamp(0, points.NumRounds - 1); + if (_FromScreenSong) + { + if (_Round == (int)EGameMode.TR_GAMEMODE_SHORTSONG) + _Round = (int)EGameMode.TR_GAMEMODE_NORMAL; + else + ++_Round; + } + else + { + CPoints points = CGame.GetPoints(); + _Round += num; + _Round = _Round.Clamp(0, points.NumRounds - 1); + } + _UpdateRound(); } @@ -307,4 +351,4 @@ namespace Vocaluxe.Screens CParty.LeavingHighscore(); } } -} \ No newline at end of file +} diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs index b5eb65ed..2d3f3a75 100644 --- a/Vocaluxe/Screens/CScreenSing.cs +++ b/Vocaluxe/Screens/CScreenSing.cs @@ -1,4 +1,4 @@ -#region license +#region license // This file is part of Vocaluxe. // // Vocaluxe is free software: you can redistribute it and/or modify @@ -30,6 +30,7 @@ using VocaluxeLib.Draw; using VocaluxeLib.Log; using VocaluxeLib.Menu; using VocaluxeLib.Menu.SingNotes; +using VocaluxeLib.PartyModes; using VocaluxeLib.Songs; namespace Vocaluxe.Screens @@ -112,7 +113,7 @@ namespace Vocaluxe.Screens private float _Length = -1f; private CVideoStream _CurrentVideo; - private EAspect _VideoAspect = EAspect.Crop; + private EAspect _VideoAspect = EAspect.Automatic; private CTextureRef _CurrentWebcamFrameTexture; private CTextureRef _Background; @@ -123,6 +124,7 @@ namespace Vocaluxe.Screens private float _RemainingTimeToFirstNote; private float _TimeToFirstNoteDuet; private float _RemainingTimeToFirstNoteDuet; + private float _TimeShowSongTextTotal; private Stopwatch _TimerSongText; private Stopwatch _TimerDuetText1; @@ -132,6 +134,7 @@ namespace Vocaluxe.Screens private bool _Webcam; private CBackground _SlideShow; + private SScreenSongOptions _Sso; public override EMusicType CurrentMusicType { @@ -287,6 +290,38 @@ namespace Vocaluxe.Screens if (CConfig.Config.Debug.SaveModifiedSongs == EOffOn.TR_CONFIG_ON) song.Save(); break; + + // Restart Round and reload song file header + case Keys.R: + if (keyEvent.Mod == EModifier.Ctrl && _Pause) + { + _SetPause(false); + _RestartRound(); + } + break; + + // Restart Round and reload song file header + case Keys.F5: + if (_Pause) + { + _SetPause(false); + _RestartRound(); + } + break; + + // Skip 30 seconds + case Keys.Right: + if (keyEvent.Mod == EModifier.Ctrl && !_Pause && !_Sso.Selection.PartyMode) + { + if (_TimerSongText.IsRunning) + _TimerSongText.Stop(); + + float newTime = _CurrentTime + 30f; + if (CSound.GetLength(_CurrentStream) < (_CurrentTime + 30f)) + newTime = CSound.GetLength(_CurrentStream) - 1f; + CSound.SetPosition(_CurrentStream, newTime); + } + break; } } @@ -356,6 +391,7 @@ namespace Vocaluxe.Screens _SetPause(false); _TimeRects.Clear(); + _Sso = CParty.GetSongSelectionOptions(); _SingNotes[_SingBars].Init(0); _AssignPlayerElements(); @@ -463,17 +499,11 @@ namespace Vocaluxe.Screens if (alpha.Length > 2) { - _Lyrics[_LyricMainDuet].Alpha = alpha[0]; - _Lyrics[_LyricSubDuet].Alpha = alpha[1]; + _Lyrics[_LyricMainDuet].Alpha = alpha[2]; + _Lyrics[_LyricSubDuet].Alpha = alpha[3]; - _Statics[_StaticLyricsDuet].Alpha = alpha[0]; - _Statics[_StaticLyricHelperDuet].Alpha = alpha[0]; - - _Lyrics[_LyricMain].Alpha = alpha[2]; - _Lyrics[_LyricSub].Alpha = alpha[3]; - - _Statics[_StaticLyrics].Alpha = alpha[2]; - _Statics[_StaticLyricHelper].Alpha = alpha[2]; + _Statics[_StaticLyricsDuet].Alpha = alpha[2]; + _Statics[_StaticLyricHelperDuet].Alpha = alpha[2]; } } @@ -532,7 +562,7 @@ namespace Vocaluxe.Screens _SingNotes[_SingBars].PlayerNotes[j].SetLine(nr); } - if (i == 0 && !song.IsDuet || i == 1 && song.IsDuet) + if (i == 0) { _Lyrics[_LyricMain].SetLine(lines[nr]); _Lyrics[_LyricMainTop].SetLine(lines[nr]); @@ -550,7 +580,7 @@ namespace Vocaluxe.Screens _Lyrics[_LyricSubTop].Clear(); } } - if (i == 0 && song.IsDuet) + if (i == 1 && song.IsDuet) { _Lyrics[_LyricMainDuet].SetLine(lines[nr]); _TimeToFirstNoteDuet = CGame.GetTimeFromBeats(lines[nr].FirstNoteBeat - lines[nr].StartBeat, song.BPM); @@ -564,7 +594,7 @@ namespace Vocaluxe.Screens } else { - if (i == 0 && !song.IsDuet || i == 1 && song.IsDuet) + if (i == 0) { _Lyrics[_LyricMain].Clear(); _Lyrics[_LyricSub].Clear(); @@ -573,7 +603,7 @@ namespace Vocaluxe.Screens _TimeToFirstNote = 0f; } - if (i == 0 && song.IsDuet) + if (i == 1 && song.IsDuet) { _Lyrics[_LyricMainDuet].Clear(); _Lyrics[_LyricSubDuet].Clear(); @@ -610,23 +640,23 @@ namespace Vocaluxe.Screens private void _UpdateSongText() { - if (_TimerSongText.IsRunning && !_Lyrics[_LyricMainDuet].Visible && !_Lyrics[_LyricMainTop].Visible) + if (_TimerSongText.IsRunning) { float t = _TimerSongText.ElapsedMilliseconds / 1000f; - if (t < 10f) + if (t < _TimeShowSongTextTotal) { _Statics[_StaticSongText].Visible = true; _Texts[_TextSongName].Visible = true; - if (t < 7f) + if (t < (_TimeShowSongTextTotal - 3f)) { _Statics[_StaticSongText].Color.A = 1f; _Texts[_TextSongName].Color.A = 1f; } else { - _Statics[_StaticSongText].Color.A = (10f - t) / 3f; - _Texts[_TextSongName].Color.A = (10f - t) / 3f; + _Statics[_StaticSongText].Color.A = (_TimeShowSongTextTotal - t) / 3f; + _Texts[_TextSongName].Color.A = (_TimeShowSongTextTotal - t) / 3f; } } else @@ -665,7 +695,7 @@ namespace Vocaluxe.Screens timer.Stop(); } } - else if (!timer.IsRunning && timer.ElapsedMilliseconds == 0 && _Lyrics[_LyricMainDuet].Alpha > 0 && CGame.GetSong().IsDuet) + else if (!timer.IsRunning && timer.ElapsedMilliseconds == 0 && _Lyrics[_LyricMainTop].Alpha > 0 && CGame.GetSong().IsDuet) timer.Start(); else textName.Visible = false; @@ -698,7 +728,7 @@ namespace Vocaluxe.Screens _TimerDuetText2.Stop(); } } - else if (!_TimerDuetText2.IsRunning && _TimerDuetText2.ElapsedMilliseconds == 0 && _Lyrics[_LyricMain].Alpha > 0 && CGame.GetSong().IsDuet) + else if (!_TimerDuetText2.IsRunning && _TimerDuetText2.ElapsedMilliseconds == 0 && _Lyrics[_LyricMainDuet].Alpha > 0 && CGame.GetSong().IsDuet) _TimerDuetText2.Start(); else _Texts[_TextDuetName2].Visible = false; @@ -794,18 +824,21 @@ namespace Vocaluxe.Screens if (_CurrentVideo != null && CConfig.Config.Video.VideosInSongs == EOffOn.TR_CONFIG_ON && !_Webcam) { background = _CurrentVideo.Texture; - aspect = _VideoAspect; } else if (_Webcam) { background = _CurrentWebcamFrameTexture; - aspect = _VideoAspect; } else background = _Background; if (background != null) { SRectF bounds = CSettings.RenderRect; + + if (_VideoAspect == EAspect.Automatic) + _VideoAspect = (background.OrigAspect <= 1.5 ? EAspect.LetterBox : EAspect.Crop); + aspect = _VideoAspect; + SRectF rect = CHelper.FitInBounds(bounds, background.OrigAspect, aspect); CDraw.DrawTexture(background, rect, background.Color, bounds); } @@ -876,7 +909,7 @@ namespace Vocaluxe.Screens _Statics[_StaticLyricHelperTop].Color.R, _Statics[_StaticLyricHelperTop].Color.G, _Statics[_StaticLyricHelperTop].Color.B, - _Statics[_StaticLyricHelperTop].Color.A * _Statics[_StaticLyricHelper].Alpha * alpha); + _Statics[_StaticLyricHelperTop].Color.A * _Statics[_StaticLyricHelperTop].Alpha * alpha); float distance = _Lyrics[_LyricMainTop].GetCurrentLyricPosX() - rect.X - rect.W; CDraw.DrawTexture(_Statics[_StaticLyricHelperTop].Texture, @@ -965,7 +998,7 @@ namespace Vocaluxe.Screens _CloseSong(); CGame.ResetPlayer(); - _LoadCurrentSong(); + _LoadCurrentSong(false); _StartSong(); } @@ -1045,7 +1078,7 @@ namespace Vocaluxe.Screens /// /// Prepare streams and screen for current song. /// - private void _LoadCurrentSong() + private void _LoadCurrentSong(bool reloadNotes = true) { if (CGame.IsFinished()) { @@ -1061,6 +1094,9 @@ namespace Vocaluxe.Screens return; } + if (!_Sso.Selection.PartyMode && (CGame.GameMode == EGameMode.TR_GAMEMODE_NORMAL || CGame.GameMode == EGameMode.TR_GAMEMODE_DUET)) + song.ReloadSong(reloadNotes); + string songname = song.Artist + " - " + song.Title; int rounds = CGame.GetNumSongs(); if (rounds > 1) @@ -1083,11 +1119,11 @@ namespace Vocaluxe.Screens voiceAssignments[i] = CGame.Players[i].VoiceNr; } + _VideoAspect = EAspect.Automatic; if (!String.IsNullOrEmpty(song.VideoFileName)) { _CurrentVideo = CVideo.Load(Path.Combine(song.Folder, song.VideoFileName)); CVideo.Skip(_CurrentVideo, song.Start, song.VideoGap); - _VideoAspect = song.VideoAspect; } CDraw.RemoveTexture(ref _Background); @@ -1145,7 +1181,21 @@ namespace Vocaluxe.Screens _TimerDuetText1.Reset(); _TimerDuetText2.Reset(); - if (!song.IsDuet) + float realGap = song.Gap - song.Start; + _TimeShowSongTextTotal = 10f; + if (_Lyrics[_LyricMainDuet].Visible || _Lyrics[_LyricMainTop].Visible) + { + if (realGap < 11f) + { + _TimeShowSongTextTotal = 0; + } + else if (realGap < 17f) + { + _TimeShowSongTextTotal = realGap - 7f; + } + } + + if (_TimeShowSongTextTotal > 0) _TimerSongText.Start(); } @@ -1196,8 +1246,8 @@ namespace Vocaluxe.Screens if (CGame.GetSong() != null && CGame.GetSong().IsDuet) { - bottomLyricsVisible = true; - topLyricsVisible = false; + bottomLyricsVisible = false; + topLyricsVisible = true; duetLyricsVisible = true; } @@ -1828,4 +1878,4 @@ namespace Vocaluxe.Screens } } } -} \ No newline at end of file +} diff --git a/Vocaluxe/Screens/CScreenSong.cs b/Vocaluxe/Screens/CScreenSong.cs index 60031c4d..42ddb6ac 100644 --- a/Vocaluxe/Screens/CScreenSong.cs +++ b/Vocaluxe/Screens/CScreenSong.cs @@ -1,4 +1,4 @@ -#region license +#region license // This file is part of Vocaluxe. // // Vocaluxe is free software: you can redistribute it and/or modify @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Timers; using System.Windows.Forms; using Vocaluxe.Base; using VocaluxeLib; @@ -42,14 +43,18 @@ 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 6; } + get { return 8; } } private const string _TextCategory = "TextCategory"; private const string _TextSelection = "TextSelection"; private const string _TextSearchBarTitle = "TextSearchBarTitle"; private const string _TextSearchBar = "TextSearchBar"; + private const string _TextHelpBar = "TextHelpBar"; + private const string _TextHelpBarSearch = "TextHelpBarSearch"; + private const string _TextHelpBarParty = "TextHelpBarParty"; private const string _TextOptionsTitle = "TextOptionsTitle"; + private const string _TextShortInfoTop = "TextShortInfoTop"; private const string _ButtonOpenOptions = "ButtonOpenOptions"; private const string _ButtonOptionsSing = "ButtonOptionsSing"; @@ -63,6 +68,7 @@ namespace Vocaluxe.Screens private const string _ButtonOptionsRandomMedley = "ButtonOptionsRandomMedley"; private const string _ButtonOptionsStartMedley = "ButtonOptionsStartMedley"; private const string _ButtonStart = "ButtonStart"; + private const string _ButtonOptionsHighscore = "ButtonOptionsHighscore"; private const string _SelectSlideOptionsMode = "SelectSlideOptionsMode"; private const string _SelectSlideOptionsPlaylistAdd = "SelectSlideOptionsPlaylistAdd"; @@ -71,12 +77,16 @@ namespace Vocaluxe.Screens private const string _StaticSearchBar = "StaticSearchBar"; private const string _StaticOptionsBG = "StaticOptionsBG"; + private const string _StaticShortInfoTop = "StaticShortInfoTop"; private const string _SongMenuName = "SongMenu"; private const string _PlaylistName = "Playlist"; private string _SearchText = String.Empty; private bool _SearchActive; + private int _JumpTo_lastCharTime = 0; + private String _JumpTo_lastSearchString = ""; + private readonly List _ButtonsJoker = new List(); private readonly List _TextsPlayer = new List(); private ESongOptionsView _CurSongOptionsView; @@ -93,6 +103,20 @@ namespace Vocaluxe.Screens private ISongMenu _SongMenu; private CPlaylist _Playlist; + private System.Timers.Timer _TimerShortInfoText; + + private static int _StaticSelectedSongID; + + private static void setStaticSelectedSongID(int songID) + { + _StaticSelectedSongID = songID; + } + + public static int getSelectedSongID() + { + return _StaticSelectedSongID; + } + public override EMusicType CurrentMusicType { get { return CSongs.IsInCategory ? EMusicType.Preview : EMusicType.Background; } @@ -124,6 +148,7 @@ namespace Vocaluxe.Screens blist.Add(_ButtonStart); blist.Add(_ButtonOptionsRandomMedley); blist.Add(_ButtonOptionsStartMedley); + blist.Add(_ButtonOptionsHighscore); _TextsPlayer.Clear(); for (int i = 0; i < CSettings.MaxNumPlayer; i++) @@ -134,9 +159,13 @@ namespace Vocaluxe.Screens tlist.Add(_TextSelection); tlist.Add(_TextSearchBarTitle); tlist.Add(_TextSearchBar); + tlist.Add(_TextHelpBar); + tlist.Add(_TextHelpBarSearch); + tlist.Add(_TextHelpBarParty); tlist.Add(_TextOptionsTitle); + tlist.Add(_TextShortInfoTop); - _ThemeStatics = new string[] {_StaticSearchBar, _StaticOptionsBG}; + _ThemeStatics = new string[] {_StaticSearchBar, _StaticOptionsBG, _StaticShortInfoTop}; _ThemeTexts = tlist.ToArray(); _ThemeButtons = blist.ToArray(); _ThemeSelectSlides = new string[] {_SelectSlideOptionsMode, _SelectSlideOptionsPlaylistAdd, _SelectSlideOptionsPlaylistOpen, _SelectSlideOptionsNumMedleySongs}; @@ -144,6 +173,10 @@ namespace Vocaluxe.Screens _ThemePlaylists = new string[] {_PlaylistName}; _DragAndDropCover = GetNewStatic(); + + _TimerShortInfoText = new System.Timers.Timer(5000); + _TimerShortInfoText.AutoReset = false; + _TimerShortInfoText.Elapsed += OnTimedEventShortInfoText; } protected override void _OnSongMenuChanged() @@ -279,6 +312,89 @@ namespace Vocaluxe.Screens else if (!_Sso.Selection.PartyMode) _SearchActive = true; break; + + case Keys.V: + if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.PartyMode) + _StartRandomVisibleSongs(); + break; + + case Keys.R: + if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.RandomOnly) + _SelectNextRandom(-1); + break; + + case Keys.S: + if (keyEvent.Mod == EModifier.Ctrl && CSongs.NumSongsVisible > 0 && !_Sso.Selection.PartyMode) + _StartMedleySong(_SongMenu.GetPreviewSongNr()); + break; + + case Keys.T: + if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.PartyMode) + { + _ToggleTabs(); + } + break; + + case Keys.D0: + case Keys.D1: + case Keys.D2: + case Keys.D3: + case Keys.D4: + case Keys.D5: + case Keys.D6: + case Keys.D7: + case Keys.D8: + case Keys.D9: + if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.PartyMode) + { + int tempSortNr = -1; + int.TryParse(keyEvent.Key.ToString().Substring(1), out tempSortNr); + + if (tempSortNr == 0) + tempSortNr = 10; + + _ToggleSort(tempSortNr); + } + break; + + case Keys.H: + if (keyEvent.Mod == EModifier.Ctrl && CSongs.NumSongsVisible > 0 && !_Sso.Selection.PartyMode) + { + _ShowHighscore(); + } + break; + + case Keys.PageUp: + if (CBase.Songs.GetTabs() == EOffOn.TR_CONFIG_OFF) + { + int numSongsPerPage = (CConfig.SongMenu == ESongMenu.TR_CONFIG_TILE_BOARD ? 24 : 15); + if (keyEvent.Mod == EModifier.Ctrl) + _SongMenu.SetSelectedSong(0); + else + { + if ((_SongMenu.GetSelectedSongNr() - numSongsPerPage) <= 0) + _SongMenu.SetSelectedSong(0); + else + _SongMenu.SetSelectedSong(_SongMenu.GetSelectedSongNr() - numSongsPerPage); + } + } + break; + + case Keys.PageDown: + if (CBase.Songs.GetTabs() == EOffOn.TR_CONFIG_OFF) + { + int numSongsPerPage = (CConfig.SongMenu == ESongMenu.TR_CONFIG_TILE_BOARD ? 24 : 15); + if (keyEvent.Mod == EModifier.Ctrl) + _SongMenu.SetSelectedSong(CSongs.NumSongsVisible - 1); + else + { + if ((_SongMenu.GetSelectedSongNr() + numSongsPerPage) >= CSongs.NumSongsVisible) + _SongMenu.SetSelectedSong(CSongs.NumSongsVisible - 1); + else + _SongMenu.SetSelectedSong(_SongMenu.GetSelectedSongNr() + numSongsPerPage); + } + } + break; } if (!_SearchActive) { @@ -293,23 +409,9 @@ namespace Vocaluxe.Screens if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.PartyMode) _StartRandomAllSongs(); break; - case Keys.V: - if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.PartyMode) - _StartRandomVisibleSongs(); - break; - - case Keys.R: - if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.RandomOnly) - _SelectNextRandom(-1); - break; - - case Keys.S: - if (keyEvent.Mod == EModifier.Ctrl && CSongs.NumSongsVisible > 0 && !_Sso.Selection.PartyMode) - _StartMedleySong(_SongMenu.GetPreviewSongNr()); - break; case Keys.F: - if (keyEvent.Mod == EModifier.Ctrl) + if (keyEvent.Mod == EModifier.Ctrl && !_Sso.Selection.PartyMode) _SearchActive = true; break; @@ -390,6 +492,10 @@ namespace Vocaluxe.Screens _ToggleSongOptions(ESongOptionsView.None); _StartRandomMedley(_SelectSlides[_SelectSlideOptionsNumMedleySongs].Selection + 1, !CSongs.IsInCategory); } + else if (_Buttons[_ButtonOptionsHighscore].Selected) + { + _ShowHighscore(); + } break; case Keys.Escape: @@ -565,6 +671,10 @@ namespace Vocaluxe.Screens _StartRandomMedley(_SelectSlides[_SelectSlideOptionsNumMedleySongs].Selection + 1, !CSongs.IsInCategory); return true; } + else if (_Buttons[_ButtonOptionsHighscore].Selected) + { + _ShowHighscore(); + } else if (_Sso.Selection.RandomOnly && _Sso.Selection.NumJokers != null) { if (_Buttons[_ButtonStart].Selected) @@ -679,6 +789,9 @@ namespace Vocaluxe.Screens _DragAndDropCover.Visible = false; _Playlist.DragAndDropSongID = -1; + _Statics[_StaticShortInfoTop].Visible = false; + _Texts[_TextShortInfoTop].Visible = false; + UpdateGame(); } @@ -727,12 +840,18 @@ namespace Vocaluxe.Screens _Texts[_TextSearchBar].Visible = true; _Texts[_TextSearchBarTitle].Visible = true; + _Texts[_TextHelpBar].Visible = false; + _Texts[_TextHelpBarSearch].Visible = true; + _Texts[_TextHelpBarParty].Visible = false; _Statics[_StaticSearchBar].Visible = true; } else { _Texts[_TextSearchBar].Visible = false; _Texts[_TextSearchBarTitle].Visible = false; + _Texts[_TextHelpBar].Visible = !_Sso.Selection.PartyMode; + _Texts[_TextHelpBarSearch].Visible = false; + _Texts[_TextHelpBarParty].Visible = _Sso.Selection.PartyMode; _Statics[_StaticSearchBar].Visible = false; } @@ -848,6 +967,55 @@ namespace Vocaluxe.Screens } } + private void _ToggleSort(int sortNr) + { + if (CBase.Songs.IsInCategory() && _Sso.Selection.CategoryChangeAllowed) + { + CBase.Songs.SetCategory(-1); + } + + CSongs.Sorter.SongSorting = (ESongSorting)sortNr; + CConfig.Config.Game.SongSorting = CSongs.Sorter.SongSorting; + _Sso.Sorting.SongSorting = CSongs.Sorter.SongSorting; + + _SongMenu.Update(_Sso); + _SongMenu.OnShow(); + + _Texts[_TextShortInfoTop].Text = CBase.Language.Translate("TR_SCREENSONG_SORTING").Replace("%s", CBase.Language.Translate(_Sso.Sorting.SongSorting.ToString())); + _Statics[_StaticShortInfoTop].Visible = true; + _Texts[_TextShortInfoTop].Visible = true; + _TimerShortInfoText.Stop(); + _TimerShortInfoText.Enabled = true; + } + + private void OnTimedEventShortInfoText(Object source, ElapsedEventArgs e) + { + _Statics[_StaticShortInfoTop].Visible = false; + _Texts[_TextShortInfoTop].Visible = false; + } + + private void _ToggleTabs() + { + EOffOn tmpStatus = CSongs.Categorizer.Tabs; + + if (tmpStatus == EOffOn.TR_CONFIG_ON) + CSongs.Categorizer.Tabs = EOffOn.TR_CONFIG_OFF; + else + CSongs.Categorizer.Tabs = EOffOn.TR_CONFIG_ON; + + CConfig.Config.Game.Tabs = CSongs.Categorizer.Tabs; + _Sso.Sorting.Tabs = CSongs.Categorizer.Tabs; + _SongMenu.Update(_Sso); + _SongMenu.OnShow(); + } + + private void _ShowHighscore() + { + CGame.ClearSongs(); + CScreenSong.setStaticSelectedSongID(CSongs.VisibleSongs[_SongMenu.GetPreviewSongNr()].ID); + CBase.Graphics.FadeTo(EScreen.Highscore); + } + private void _StartSong(int songNr) { if (CSongs.IsInCategory && (songNr >= 0)) @@ -1042,8 +1210,14 @@ namespace Vocaluxe.Screens private void _JumpTo(char letter) { + // Stefan1200: Add all letters from a key press within one second to a search string. Clear search string, if last key press is older than one second. + String searchString; + if (Environment.TickCount - _JumpTo_lastCharTime < 1000) + searchString = _JumpTo_lastSearchString + letter.ToString(); + else + searchString = letter.ToString(); + int start = 0; - int curSelected = CSongs.IsInCategory ? _SongMenu.GetSelectedSongNr() : _SongMenu.GetSelectedCategory(); bool firstLevel = CConfig.Config.Game.Tabs == EOffOn.TR_CONFIG_OFF && CSongs.IsInCategory; bool secondSort = CConfig.Config.Game.Tabs == EOffOn.TR_CONFIG_ON && (CConfig.Config.Game.SongSorting == ESongSorting.TR_CONFIG_ARTIST || @@ -1055,34 +1229,25 @@ namespace Vocaluxe.Screens //TODO: What's to do with multiple tags? //Flamefire: What? We only sorted by one tag, sorting by multiple tags (e.g. Album) will be by e.g. the first entry. That can be used here too as otherwhise it will confuse users because it jumps randomly ReadOnlyCollection songs = CSongs.VisibleSongs; - int ct = songs.Count; int visibleID = -1; switch (CConfig.Config.Game.SongSorting) { case ESongSorting.TR_CONFIG_ARTIST: case ESongSorting.TR_CONFIG_ARTIST_LETTER: - if (curSelected >= 0 && curSelected < ct - 1 && songs[curSelected].Artist.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)) - start = curSelected + 1; - visibleID = _FindIndex(songs, start, element => element.Artist.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)); + visibleID = _FindIndex(songs, start, element => element.Artist.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)); break; case ESongSorting.TR_CONFIG_YEAR: case ESongSorting.TR_CONFIG_DECADE: - if (curSelected >= 0 && curSelected < ct - 1 && songs[curSelected].Year.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)) - start = curSelected + 1; - visibleID = _FindIndex(songs, start, element => element.Year.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)); + visibleID = _FindIndex(songs, start, element => element.Year.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)); break; case ESongSorting.TR_CONFIG_TITLE_LETTER: - if (curSelected >= 0 && curSelected < ct - 1 && songs[curSelected].Title.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)) - start = curSelected + 1; - visibleID = _FindIndex(songs, start, element => element.Title.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)); + visibleID = _FindIndex(songs, start, element => element.Title.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)); break; case ESongSorting.TR_CONFIG_FOLDER: - if (curSelected >= 0 && curSelected < ct - 1 && songs[curSelected].Folder.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)) - start = curSelected + 1; - visibleID = _FindIndex(songs, start, element => element.Folder.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)); + visibleID = _FindIndex(songs, start, element => element.FolderName.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)); break; } if (visibleID > -1) @@ -1091,22 +1256,17 @@ namespace Vocaluxe.Screens else if (secondSort && CSongs.IsInCategory) { ReadOnlyCollection songs = CSongs.VisibleSongs; - int ct = songs.Count; int visibleID = -1; switch (CConfig.Config.Game.SongSorting) { case ESongSorting.TR_CONFIG_FOLDER: case ESongSorting.TR_CONFIG_TITLE_LETTER: - if (curSelected >= 0 && curSelected < ct - 1 && songs[curSelected].Artist.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)) - start = curSelected + 1; - visibleID = _FindIndex(songs, start, element => element.Artist.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)); + visibleID = _FindIndex(songs, start, element => element.Artist.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)); break; case ESongSorting.TR_CONFIG_ARTIST: case ESongSorting.TR_CONFIG_ARTIST_LETTER: - if (curSelected >= 0 && curSelected < ct - 1 && songs[curSelected].Title.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)) - start = curSelected + 1; - visibleID = _FindIndex(songs, start, element => element.Title.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)); + visibleID = _FindIndex(songs, start, element => element.Title.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)); break; } if (visibleID > -1) @@ -1115,13 +1275,14 @@ namespace Vocaluxe.Screens else if (!CSongs.IsInCategory) { ReadOnlyCollection categories = CSongs.Categories; - int ct = categories.Count; - if (curSelected >= 0 && curSelected < ct - 1 && categories[curSelected].Name.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)) - start = curSelected + 1; - int visibleID = _FindIndex(categories, start, element => element.Name.StartsWith(letter.ToString(), StringComparison.OrdinalIgnoreCase)); + int visibleID = _FindIndex(categories, start, element => element.Name.StartsWith(searchString, StringComparison.OrdinalIgnoreCase)); if (visibleID > -1) _SongMenu.SetSelectedCategory(visibleID); } + + // Stefan1200: Remember search string and current TickCount in class variables. + _JumpTo_lastCharTime = Environment.TickCount; + _JumpTo_lastSearchString = searchString; } private void _ApplyNewSearchFilter(string newFilterString) @@ -1176,6 +1337,7 @@ namespace Vocaluxe.Screens _Buttons[_ButtonOptionsOpenSelectedItem].Visible = false; _Buttons[_ButtonOptionsRandomMedley].Visible = false; _Buttons[_ButtonOptionsStartMedley].Visible = false; + _Buttons[_ButtonOptionsHighscore].Visible = false; _Texts[_TextOptionsTitle].Visible = false; _Statics[_StaticOptionsBG].Visible = false; _Buttons[_ButtonOpenOptions].Visible = true; @@ -1232,6 +1394,7 @@ namespace Vocaluxe.Screens _SelectSlides[_SelectSlideOptionsPlaylistAdd].Visible = true; _Buttons[_ButtonOptionsSing].Visible = true; _Buttons[_ButtonOptionsPlaylist].Visible = true; + _Buttons[_ButtonOptionsHighscore].Visible = true; _SelectElement(_Buttons[_ButtonOptionsSing]); _SetSelectSlidePlaylistToCurrentPlaylist(); } @@ -1395,4 +1558,4 @@ namespace Vocaluxe.Screens } #endregion Playlist Actions } -} \ No newline at end of file +} diff --git a/VocaluxeLib/CHelper.cs b/VocaluxeLib/CHelper.cs index 20efe943..fa5fb2f4 100644 --- a/VocaluxeLib/CHelper.cs +++ b/VocaluxeLib/CHelper.cs @@ -1,4 +1,4 @@ -#region license +#region license // This file is part of Vocaluxe. // // Vocaluxe is free software: you can redistribute it and/or modify @@ -101,6 +101,7 @@ namespace VocaluxeLib switch (aspect) { + case EAspect.Automatic: case EAspect.Crop: if (boundsAspectRatio >= aspectRatio) { @@ -138,7 +139,12 @@ namespace VocaluxeLib } break; case EAspect.LetterBox: - if (boundsAspectRatio <= aspectRatio) + if (boundsAspectRatio == aspectRatio) // Pillarbox + { + scaledWidth = bounds.W * 0.77f; + scaledHeight = bounds.W / aspectRatio; + } + else if (boundsAspectRatio < aspectRatio) { scaledWidth = bounds.W; scaledHeight = bounds.W / aspectRatio; @@ -306,4 +312,4 @@ namespace VocaluxeLib return bmp; } } -} \ No newline at end of file +} diff --git a/VocaluxeLib/Enums.cs b/VocaluxeLib/Enums.cs index 8ba2a416..84252cfa 100644 --- a/VocaluxeLib/Enums.cs +++ b/VocaluxeLib/Enums.cs @@ -64,6 +64,7 @@ namespace VocaluxeLib #region Fonts public enum EAspect { + Automatic, Crop, LetterBox, Stretch, @@ -436,4 +437,4 @@ namespace VocaluxeLib TR_USERROLE_PROFILEEDITOR = 32 // ReSharper restore InconsistentNaming } -} \ No newline at end of file +} diff --git a/VocaluxeLib/Log/CLog.cs b/VocaluxeLib/Log/CLog.cs index 2b78b8cb..6d1d3535 100644 --- a/VocaluxeLib/Log/CLog.cs +++ b/VocaluxeLib/Log/CLog.cs @@ -198,7 +198,7 @@ namespace VocaluxeLib.Log { if (i >= propertyValues.Length) return match.Value; - return propertyValues[i++].ToString(); + return "\"" + propertyValues[i++] + "\""; }); } diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs b/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs index 02cfac02..f02a7e44 100644 --- a/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs +++ b/VocaluxeLib/Menu/SongMenu/CSongMenuFramework.cs @@ -220,7 +220,7 @@ namespace VocaluxeLib.Menu.SongMenu EScreen check = CBase.Graphics.GetNextScreenType(); if (CBase.Graphics.GetNextScreenType() == EScreen.Sing) _ResetPreview(false); - else if (CBase.Graphics.GetNextScreenType() != EScreen.Names || CBase.Config.GetBackgroundMusicStatus() == EBackgroundMusicOffOn.TR_CONFIG_OFF) + else if ((CBase.Graphics.GetNextScreenType() != EScreen.Names && CBase.Graphics.GetNextScreenType() != EScreen.Highscore) || CBase.Config.GetBackgroundMusicStatus() == EBackgroundMusicOffOn.TR_CONFIG_OFF) _ResetPreview(); } @@ -288,7 +288,9 @@ namespace VocaluxeLib.Menu.SongMenu public void LeaveSelectedCategory() { - _LeaveCategory(); + // Stefan1200: This was implemented with the pull request #359 and is the reason for the bug described in issue #390. + // Currently disabled until we know if this is still needed or we find a better solution! + // _LeaveCategory(); } public virtual void UnloadSkin() {} @@ -425,4 +427,4 @@ namespace VocaluxeLib.Menu.SongMenu } #endregion ThemeEdit } -} \ No newline at end of file +} diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenuList.cs b/VocaluxeLib/Menu/SongMenu/CSongMenuList.cs index 2c85058a..0221206d 100644 --- a/VocaluxeLib/Menu/SongMenu/CSongMenuList.cs +++ b/VocaluxeLib/Menu/SongMenu/CSongMenuList.cs @@ -511,7 +511,9 @@ namespace VocaluxeLib.Menu.SongMenu } _TextBG.Draw(); - CTextureRef vidtex = CBase.BackgroundMusic.IsPlayingPreview() ? CBase.BackgroundMusic.GetVideoTexture() : null; + CTextureRef vidtex = null; + if (CBase.Config.GetVideoPreview() == EOffOn.TR_CONFIG_ON) + vidtex = (CBase.BackgroundMusic.IsPlayingPreview() ? CBase.BackgroundMusic.GetVideoTexture() : null); if (vidtex != null) { @@ -592,13 +594,28 @@ namespace VocaluxeLib.Menu.SongMenu private void _UpdateList(bool force = false) { + bool isInCategory = CBase.Songs.IsInCategory(); + int itemCount = isInCategory ? CBase.Songs.GetNumSongsVisible() : CBase.Songs.GetNumCategories(); + int halfListLength = _ListLength / 2; int offset; + if (_SelectionNr < _Offset && _SelectionNr >= 0) - offset = _SelectionNr; + { + if (_SelectionNr - halfListLength >= 0) + offset = _SelectionNr - halfListLength; + else + offset = 0; + } else if (_SelectionNr >= _Offset + _ListLength) - offset = _SelectionNr - _ListLength + 1; + { + if (_SelectionNr + halfListLength > itemCount) + offset = itemCount - _ListLength; + else + offset = _SelectionNr - halfListLength; + } else offset = _Offset; + _UpdateList(offset, force); } @@ -653,4 +670,4 @@ namespace VocaluxeLib.Menu.SongMenu base.LoadSkin(); } } -} \ No newline at end of file +} diff --git a/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs b/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs index 18bcad8f..478c918b 100644 --- a/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs +++ b/VocaluxeLib/Menu/SongMenu/CSongMenuTileBoard.cs @@ -485,7 +485,9 @@ namespace VocaluxeLib.Menu.SongMenu _TextBG.Draw(); - CTextureRef vidtex = CBase.BackgroundMusic.IsPlayingPreview() ? CBase.BackgroundMusic.GetVideoTexture() : null; + CTextureRef vidtex = null; + if (CBase.Config.GetVideoPreview() == EOffOn.TR_CONFIG_ON) + vidtex = (CBase.BackgroundMusic.IsPlayingPreview() ? CBase.BackgroundMusic.GetVideoTexture() : null); if (vidtex != null) { @@ -608,4 +610,4 @@ namespace VocaluxeLib.Menu.SongMenu Init(); } } -} \ No newline at end of file +} diff --git a/VocaluxeLib/Songs/CSong.cs b/VocaluxeLib/Songs/CSong.cs index e6ddaf4d..bc101698 100644 --- a/VocaluxeLib/Songs/CSong.cs +++ b/VocaluxeLib/Songs/CSong.cs @@ -101,7 +101,7 @@ namespace VocaluxeLib.Songs public readonly List BackgroundFileNames = new List(); public string VideoFileName = String.Empty; - public EAspect VideoAspect = EAspect.Crop; + public EAspect VideoAspect = EAspect.Automatic; public bool NotesLoaded { get; private set; } @@ -288,6 +288,17 @@ namespace VocaluxeLib.Songs return loader.ReadNotes(); } + public bool ReloadSong(bool reloadNotes) + { + var loader = new CSongLoader(this); + bool retValue = loader.ReadHeader(); + if (!retValue) + return false; + + retValue = loader.ReadNotes(reloadNotes); + return retValue; + } + public bool Save() { return Save(Path.Combine(Folder, FileName)); @@ -518,4 +529,4 @@ namespace VocaluxeLib.Songs ShortEnd.Source = EDataSource.Calculated; } } -} \ No newline at end of file +} diff --git a/VocaluxeLib/Songs/CSongLoader.cs b/VocaluxeLib/Songs/CSongLoader.cs index 99702bc8..ca642b4c 100644 --- a/VocaluxeLib/Songs/CSongLoader.cs +++ b/VocaluxeLib/Songs/CSongLoader.cs @@ -82,12 +82,16 @@ namespace VocaluxeLib.Songs _Song.Languages.Clear(); _Song.Genres.Clear(); _Song.UnknownTags.Clear(); + _Song.BackgroundFileNames.Clear(); _Song._Comment = ""; _Song.ManualEncoding = false; _Song.Medley.Source = EDataSource.None; _Song._CalculateMedley = true; _Song.Preview.Source = EDataSource.None; _Song.ShortEnd.Source = EDataSource.None; + _Song.Start = 0; + _Song.VideoGap = 0; + _Song.Preview.StartTime = 0; var headerFlags = new EHeaderFlags(); StreamReader sr = null; @@ -761,4 +765,4 @@ namespace VocaluxeLib.Songs } } } -} \ No newline at end of file +} diff --git a/VocaluxeLib/Utils/Player/CSongPlayer.cs b/VocaluxeLib/Utils/Player/CSongPlayer.cs index 3ae765f4..7f166ea1 100644 --- a/VocaluxeLib/Utils/Player/CSongPlayer.cs +++ b/VocaluxeLib/Utils/Player/CSongPlayer.cs @@ -110,6 +110,7 @@ namespace VocaluxeLib.Utils.Player if (_Video != null || !SongHasVideo) return; + string videoFilePath = Path.Combine(_Song.Folder, _Song.VideoFileName); _Video = CBase.Video.Load(videoFilePath); if (_Video == null) @@ -175,4 +176,4 @@ namespace VocaluxeLib.Utils.Player _CloseVideo(); } } -} \ No newline at end of file +} diff --git a/appveyor.yml b/appveyor.yml index 8fdf1640..25696802 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,7 @@ platform: clone_depth: 15 environment: GitHubKey: - secure: JSlN/em0JdspVn8jwaQ4IjugY6OQi0au4Qq0rhctJmcfGMaEGnUAOmDFULI48REW + secure: sGetWh2XUYs95VBT+QYNPtDW9Rh2/JBuxNNYXytpn7mMudUMcjSKDGErkCTum+ZE init: - git config --global core.autocrlf true install: @@ -63,7 +63,7 @@ before_build: choco install "msbuild-sonarqube-runner" -y SonarScanner.MSBuild.exe begin ` /k:"Vocaluxe" ` - /d:sonar.organization="vocaluxe" ` + /o:"vocaluxe" ` /d:sonar.host.url="https://sonarcloud.io" ` /d:sonar.login="$Env:SonarQubeToken" ` /d:"sonar.pullrequest.key=$env:APPVEYOR_PULL_REQUEST_NUMBER" ` @@ -74,7 +74,7 @@ before_build: choco install "msbuild-sonarqube-runner" -y SonarScanner.MSBuild.exe begin ` /k:"Vocaluxe" ` - /d:sonar.organization="vocaluxe" ` + /o:"vocaluxe" ` /d:sonar.host.url="https://sonarcloud.io" ` /v:"$Env:GIT_VERSION_TAG" ` /d:sonar.login="$Env:SonarQubeToken" ` @@ -135,7 +135,7 @@ deploy: release: $(APPVEYOR_REPO_TAG_NAME) description: $(APPVEYOR_REPO_COMMIT) auth_token: - secure: JSlN/em0JdspVn8jwaQ4IjugY6OQi0au4Qq0rhctJmcfGMaEGnUAOmDFULI48REW + secure: sGetWh2XUYs95VBT+QYNPtDW9Rh2/JBuxNNYXytpn7mMudUMcjSKDGErkCTum+ZE artifact: ReleaseZip prerelease: $(IS_BETA_RELEASE) on: @@ -147,7 +147,7 @@ deploy: release: Latest Nightly build description: $(APPVEYOR_REPO_COMMIT) auth_token: - secure: JSlN/em0JdspVn8jwaQ4IjugY6OQi0au4Qq0rhctJmcfGMaEGnUAOmDFULI48REW + secure: sGetWh2XUYs95VBT+QYNPtDW9Rh2/JBuxNNYXytpn7mMudUMcjSKDGErkCTum+ZE artifact: ReleaseZip prerelease: true on: