Runtime and build - Move all projects to .NET 10 with SDK-style project files and a shared Directory.Build.props (WIN/LINUX, x86/x64 defines) - Load managed and unmanaged dependencies from libs/managed and libs/unmanaged through assembly and native library resolvers - Compile party modes with Roslyn instead of CodeDom - Update AppVeyor to the .NET 10 SDK and dotnet test - Download the FFmpeg and gstreamer runtimes from the dependencies repository during the build - Remove the VC++ 2015-2022 runtime check, no dependency needs it anymore Graphics and windowing - Replace the Direct3D 9 renderer with Direct3D 11 (Vortice) - Pace Direct3D 11 frames with a frame latency waitable swap chain - Move window, input and message boxes to SDL3 - Replace System.Drawing with SkiaSharp and WinForms with SDL3 and a software renderer Video and audio - Replace Acinerella with FFmpeg 8.1.3 (FFmpeg.AutoGen) - Add hardware accelerated video decoding (D3D11VA, DXVA2, VideoToolbox, VAAPI, VDPAU) with software fallback - Convert YUV video frames to RGB on the GPU in Direct3D 11 and OpenGL - Add the video options HardwareDecoding, GpuColorConversion, DecoderThreads and VideoDownscaleResolution - Update OpenAL to OpenTK 4 and NAudio recording to WasapiRecorder Fixes - Fix the song preview start and shorten the reporter buttons - Fix a crash when opening the highscore without a selected song - Use the options slide highlight in the party mode screens to avoid brightness flicker on VRR displays - Disable GameInput in the x86 build, SDL3 crashes in GameInputCreate on 32-bit systems with the GameInput runtime installed - Fix a truncation warning in PitchTracker
290 lines
10 KiB
C#
290 lines
10 KiB
C#
#region license
|
|
// This file is part of Vocaluxe.
|
|
//
|
|
// Vocaluxe is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Vocaluxe is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace VocaluxeLib.Menu
|
|
{
|
|
public abstract class CMenuPartySongSelection : CMenuParty
|
|
{
|
|
private const string _ButtonNext = "ButtonNext";
|
|
private const string _ButtonBack = "ButtonBack";
|
|
|
|
private const string _SelectSlideSongMode = "SelectSlideSongMode";
|
|
private const string _SelectSlideSource = "SelectSlideSource";
|
|
private const string _SelectSlidePlaylist = "SelectSlidePlaylist";
|
|
private const string _SelectSlideSorting = "SelectSlideSorting";
|
|
private const string _SelectSlideCategory = "SelectSlideCategory";
|
|
private const string _SelectSlideNumMedleySongs = "SelectSlideNumMedleySongs";
|
|
|
|
protected int Playlist;
|
|
protected EGameMode SongMode
|
|
{
|
|
get { return AllowedSongModes[_SongMode]; }
|
|
set
|
|
{
|
|
_SongMode = 0;
|
|
for (var i = 0; i < AllowedSongModes.Length; i++)
|
|
{
|
|
if (AllowedSongModes[i] == value)
|
|
{
|
|
_SongMode = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private int _SongMode;
|
|
|
|
protected ESongSource Source
|
|
{
|
|
get { return AllowedSongSources[_Source]; }
|
|
set
|
|
{
|
|
_Source = 0;
|
|
for (var i = 0; i < AllowedSongSources.Length; i++)
|
|
{
|
|
if (AllowedSongSources[i] == value)
|
|
{
|
|
_Source = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private int _Source;
|
|
|
|
protected ESongSorting Sorting
|
|
{
|
|
get { return AllowedSongSorting[_Sorting]; }
|
|
set
|
|
{
|
|
_Sorting = 0;
|
|
for (var i = 0; i < AllowedSongSorting.Length; i++)
|
|
{
|
|
if (AllowedSongSorting[i] == value)
|
|
{
|
|
_Sorting = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private int _Sorting;
|
|
|
|
protected int Category;
|
|
|
|
protected EGameMode[] AllowedSongModes;
|
|
protected ESongSource[] AllowedSongSources;
|
|
protected ESongSorting[] AllowedSongSorting;
|
|
|
|
protected int NumMedleySongs = 5;
|
|
protected int NumMinMedleySongs = 3;
|
|
protected int NumMaxMedleySongs = 10;
|
|
|
|
private List<int> _PlaylistIds;
|
|
|
|
public override void Init()
|
|
{
|
|
base.Init();
|
|
|
|
_ThemeButtons = new string[] { _ButtonNext, _ButtonBack };
|
|
_ThemeSelectSlides = new string[]
|
|
{ _SelectSlideSongMode, _SelectSlideSource, _SelectSlidePlaylist, _SelectSlideSorting, _SelectSlideCategory, _SelectSlideNumMedleySongs };
|
|
|
|
_SetAllowedOptions();
|
|
}
|
|
|
|
public override bool HandleInput(SKeyEvent keyEvent)
|
|
{
|
|
base.HandleInput(keyEvent);
|
|
|
|
switch (keyEvent.Key)
|
|
{
|
|
case Keys.Back:
|
|
case Keys.Escape:
|
|
Back();
|
|
break;
|
|
case Keys.Enter:
|
|
if (_Buttons[_ButtonNext].Selected)
|
|
{
|
|
Next();
|
|
}
|
|
else if (_Buttons[_ButtonBack].Selected)
|
|
{
|
|
Back();
|
|
}
|
|
|
|
break;
|
|
|
|
case Keys.Left:
|
|
case Keys.Right:
|
|
_GetSelectedOptions();
|
|
_UpdateSelectSlideVisibility();
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override bool HandleMouse(SMouseEvent mouseEvent)
|
|
{
|
|
base.HandleMouse(mouseEvent);
|
|
|
|
if (mouseEvent.LB && _IsMouseOverCurSelection(mouseEvent))
|
|
{
|
|
if (_Buttons[_ButtonBack].Selected)
|
|
{
|
|
Back();
|
|
}
|
|
else if (_Buttons[_ButtonNext].Selected)
|
|
{
|
|
Next();
|
|
}
|
|
else
|
|
{
|
|
_GetSelectedOptions();
|
|
_UpdateSelectSlideVisibility();
|
|
}
|
|
}
|
|
else if (mouseEvent.RB)
|
|
{
|
|
Back();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public abstract void Back();
|
|
public abstract void Next();
|
|
|
|
public override void OnShow()
|
|
{
|
|
base.OnShow();
|
|
|
|
CBase.Songs.SortSongs(Sorting, EOffOn.TR_CONFIG_ON, CBase.Config.GetIgnoreArticles(), "", EDuetOptions.All, -1);
|
|
|
|
_FillSlides();
|
|
_SetSelectedOptions();
|
|
_UpdateSelectSlideVisibility();
|
|
}
|
|
|
|
private void _FillSlides()
|
|
{
|
|
_SelectSlides[_SelectSlideSongMode].Clear();
|
|
foreach (var gm in AllowedSongModes)
|
|
{
|
|
_SelectSlides[_SelectSlideSongMode].AddValue(gm.ToString());
|
|
}
|
|
|
|
_SelectSlides[_SelectSlideSource].Clear();
|
|
foreach (var ss in AllowedSongSources)
|
|
{
|
|
_SelectSlides[_SelectSlideSource].AddValue(ss.ToString());
|
|
}
|
|
|
|
_SelectSlides[_SelectSlideSorting].Clear();
|
|
foreach (var ss in AllowedSongSorting)
|
|
{
|
|
_SelectSlides[_SelectSlideSorting].AddValue(ss.ToString());
|
|
}
|
|
|
|
_SelectSlides[_SelectSlidePlaylist].Clear();
|
|
_SelectSlides[_SelectSlidePlaylist].NumVisible = 1; // Make sure that only one playlist at a time will be displayed (or the names overlap)
|
|
_PlaylistIds = CBase.Playlist.GetIds();
|
|
var playlists = CBase.Playlist.GetNames();
|
|
for (var i = 0; i < playlists.Count; i++)
|
|
{
|
|
var value = playlists[i] + " (" + CBase.Playlist.GetSongCount(i) + " " + CBase.Language.Translate("TR_SONGS", PartyModeId) + ")";
|
|
_SelectSlides[_SelectSlidePlaylist].AddValue(value);
|
|
}
|
|
|
|
_SelectSlides[_SelectSlideNumMedleySongs].Clear();
|
|
for (var num = NumMinMedleySongs; num <= NumMaxMedleySongs; num++)
|
|
{
|
|
_SelectSlides[_SelectSlideNumMedleySongs].AddValue(num + " " + CBase.Language.Translate("TR_SONGS", PartyModeId));
|
|
}
|
|
|
|
_FillCategorySlide();
|
|
}
|
|
|
|
private void _FillCategorySlide()
|
|
{
|
|
_SelectSlides[_SelectSlideCategory].Clear();
|
|
for (var i = 0; i < CBase.Songs.GetNumCategories(); i++)
|
|
{
|
|
var cat = CBase.Songs.GetCategory(i);
|
|
var value = cat.Name + " (" + cat.GetNumSongsNotSung() + " " + CBase.Language.Translate("TR_SONGS", PartyModeId) + ")";
|
|
_SelectSlides[_SelectSlideCategory].AddValue(value);
|
|
}
|
|
}
|
|
|
|
private void _GetSelectedOptions()
|
|
{
|
|
_SongMode = _SelectSlides[_SelectSlideSongMode].Selection;
|
|
_Source = _SelectSlides[_SelectSlideSource].Selection;
|
|
NumMedleySongs = NumMinMedleySongs + _SelectSlides[_SelectSlideNumMedleySongs].Selection;
|
|
|
|
var playlistSelection = _SelectSlides[_SelectSlidePlaylist].Selection;
|
|
if (playlistSelection >= 0 && playlistSelection < _PlaylistIds.Count)
|
|
{
|
|
Playlist = _PlaylistIds[playlistSelection];
|
|
}
|
|
else
|
|
{
|
|
Playlist = -1;
|
|
}
|
|
|
|
if (_SelectSlides[_SelectSlideSorting].Selection != _Sorting)
|
|
{
|
|
_Sorting = _SelectSlides[_SelectSlideSorting].Selection;
|
|
CBase.Songs.SortSongs(Sorting, EOffOn.TR_CONFIG_ON, CBase.Config.GetIgnoreArticles(), "", EDuetOptions.All, -1);
|
|
_FillCategorySlide();
|
|
|
|
_SelectSlides[_SelectSlideCategory].Selection = 0;
|
|
}
|
|
|
|
Category = _SelectSlides[_SelectSlideCategory].Selection;
|
|
}
|
|
|
|
private void _SetSelectedOptions()
|
|
{
|
|
_SelectSlides[_SelectSlideSongMode].Selection = _SongMode;
|
|
_SelectSlides[_SelectSlideSource].Selection = _Source;
|
|
_SelectSlides[_SelectSlideNumMedleySongs].Selection = NumMedleySongs - NumMinMedleySongs;
|
|
_SelectSlides[_SelectSlidePlaylist].Selection = Playlist;
|
|
_SelectSlides[_SelectSlideSorting].Selection = _Sorting;
|
|
_SelectSlides[_SelectSlideCategory].Selection = Category;
|
|
}
|
|
|
|
private void _UpdateSelectSlideVisibility()
|
|
{
|
|
_SelectSlides[_SelectSlideNumMedleySongs].Visible = SongMode == EGameMode.TR_GAMEMODE_MEDLEY;
|
|
_SelectSlides[_SelectSlidePlaylist].Visible = Source == ESongSource.TR_SONGSOURCE_PLAYLIST;
|
|
_SelectSlides[_SelectSlideSorting].Visible = Source == ESongSource.TR_SONGSOURCE_CATEGORY;
|
|
_SelectSlides[_SelectSlideCategory].Visible = Source == ESongSource.TR_SONGSOURCE_CATEGORY;
|
|
}
|
|
|
|
protected virtual void _SetAllowedOptions()
|
|
{
|
|
AllowedSongModes = (EGameMode[])Enum.GetValues(typeof(EGameMode));
|
|
AllowedSongSources = (ESongSource[])Enum.GetValues(typeof(ESongSource));
|
|
AllowedSongSorting = (ESongSorting[])Enum.GetValues(typeof(ESongSorting));
|
|
}
|
|
}
|
|
} |