#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 . #endregion using System; using System.Collections.Generic; using System.Diagnostics; using VocaluxeLib.Menu; namespace VocaluxeLib.PartyModes.PartnerSwap { class CRankRow { public CSwapPlayer Player; public CStatic Highlight; public CStatic Avatar; public CText Pos; public CText Name; public CText Songs; public CText Average; public int OldRank; public int NewRank; } public class CPartyScreenPartnerSwapMain : CPartyScreenPartnerSwap { protected override int _ScreenVersion { get { return 1; } } private const string _TextPopupReallyExit = "TextPopupReallyExit"; private const string _TextPass = "TextPass"; private const string _TextRowPos = "TextRowPos"; private const string _TextRowName = "TextRowName"; private const string _TextRowSongs = "TextRowSongs"; private const string _TextRowAverage = "TextRowAverage"; private const string _TextPairName1 = "TextPairName1"; private const string _TextPairName2 = "TextPairName2"; private const string _TextAmp = "TextAmp"; private const string _TextTogether = "TextTogether"; private const string _TextPause = "TextPause"; private const string _TextLastResult = "TextLastResult"; private const string _TextHarmony = "TextHarmony"; private const string _TextBestLabel = "TextBestLabel"; private const string _TextBestNames = "TextBestNames"; private const string _TextBestScore = "TextBestScore"; private const string _TextChampionLabel = "TextChampionLabel"; private const string _TextChampion = "TextChampion"; private const string _ButtonNextRound = "ButtonNextRound"; private const string _ButtonBack = "ButtonBack"; private const string _ButtonExit = "ButtonExit"; private const string _ButtonPopupYes = "ButtonPopupYes"; private const string _ButtonPopupNo = "ButtonPopupNo"; private const string _StaticPopupBG = "StaticPopupBG"; private const string _StaticRowHighlight = "StaticRowHighlight"; private const string _StaticRowAvatar = "StaticRowAvatar"; private const string _StaticPairAvatar1 = "StaticPairAvatar1"; private const string _StaticPairAvatar2 = "StaticPairAvatar2"; private const string _StaticBestAvatar1 = "StaticBestAvatar1"; private const string _StaticBestAvatar2 = "StaticBestAvatar2"; private const string _ParticleEffectChampion = "ParticleEffectChampion"; private const float _FirstRowY = 260f; private const float _RowStep = 54f; private const float _RankDelay = 300f; private const float _RankDuration = 700f; private const float _PopDuration = 700f; private readonly string[] _RankColors = new string[] { "Top1Color", "Top2Color", "Top3Color" }; private bool _ExitPopupVisible; private List _Rows; private readonly Stopwatch _AnimTimer = new Stopwatch(); private bool _ShowNewResult; private int _LastSeenSongs = -1; private float _LastResultHeight; private float _HarmonyHeight; private float _ChampionHeight; private SRectF _PairAvatar1Rect; public override void Init() { base.Init(); _ThemeTexts = new string[] { _TextPopupReallyExit, _TextPass, _TextRowPos, _TextRowName, _TextRowSongs, _TextRowAverage, _TextPairName1, _TextPairName2, _TextAmp, _TextTogether, _TextPause, _TextLastResult, _TextHarmony, _TextBestLabel, _TextBestNames, _TextBestScore, _TextChampionLabel, _TextChampion }; _ThemeButtons = new string[] { _ButtonNextRound, _ButtonBack, _ButtonExit, _ButtonPopupYes, _ButtonPopupNo }; _ThemeStatics = new string[] { _StaticPopupBG, _StaticRowHighlight, _StaticRowAvatar, _StaticPairAvatar1, _StaticPairAvatar2, _StaticBestAvatar1, _StaticBestAvatar2 }; _ThemeParticleEffects = new string[] { _ParticleEffectChampion }; } public override void LoadTheme(string xmlPath) { base.LoadTheme(xmlPath); _Rows = new List(); for (var i = 0; i < _PartyMode.MaxPlayers; i++) { var row = new CRankRow { Highlight = GetNewStatic(_Statics[_StaticRowHighlight]), Avatar = GetNewStatic(_Statics[_StaticRowAvatar]), Pos = GetNewText(_Texts[_TextRowPos]), Name = GetNewText(_Texts[_TextRowName]), Songs = GetNewText(_Texts[_TextRowSongs]), Average = GetNewText(_Texts[_TextRowAverage]) }; row.Avatar.Aspect = EAspect.Crop; _AddStatic(row.Highlight); _AddStatic(row.Avatar); _AddText(row.Pos); _AddText(row.Name); _AddText(row.Songs); _AddText(row.Average); _Rows.Add(row); } _Statics[_StaticRowHighlight].Visible = false; _Statics[_StaticRowAvatar].Visible = false; _Texts[_TextRowPos].Visible = false; _Texts[_TextRowName].Visible = false; _Texts[_TextRowSongs].Visible = false; _Texts[_TextRowAverage].Visible = false; _Statics[_StaticPairAvatar1].Aspect = EAspect.Crop; _Statics[_StaticPairAvatar2].Aspect = EAspect.Crop; _Statics[_StaticBestAvatar1].Aspect = EAspect.Crop; _Statics[_StaticBestAvatar2].Aspect = EAspect.Crop; _PairAvatar1Rect = _Statics[_StaticPairAvatar1].Rect; _LastResultHeight = _Texts[_TextLastResult].Font.Height; _HarmonyHeight = _Texts[_TextHarmony].Font.Height; _ChampionHeight = _Texts[_TextChampion].Font.Height; } public override bool HandleInput(SKeyEvent keyEvent) { base.HandleInput(keyEvent); if (!keyEvent.KeyPressed) { switch (keyEvent.Key) { case Keys.Back: case Keys.Escape: _OnBack(); break; case Keys.Enter: _OnSelect(); break; } } return true; } public override bool HandleMouse(SMouseEvent mouseEvent) { base.HandleMouse(mouseEvent); if (mouseEvent.LB && _IsMouseOverCurSelection(mouseEvent)) { _OnSelect(); } if (mouseEvent.RB) { _OnBack(); } return true; } public override void OnShow() { base.OnShow(); _ShowNewResult = _PartyMode.GameData.LastPair != null && _PartyMode.GameData.NumSongsSung != _LastSeenSongs; _LastSeenSongs = _PartyMode.GameData.NumSongsSung; _UpdateRanking(); _UpdatePair(); _UpdateBestPair(); _UpdateLastResult(); _AnimTimer.Reset(); _AnimTimer.Start(); _UpdateAnimations(); var started = _PartyMode.GameData.NumSongsSung > 0; _Buttons[_ButtonBack].Visible = !started; _Buttons[_ButtonExit].Visible = started; _Buttons[_ButtonNextRound].Visible = !_PartyMode.IsFinished; _ShowPopup(false); if (_PartyMode.IsFinished) { _SelectElement(_Buttons[_ButtonExit]); } else { _SelectElement(_Buttons[_ButtonNextRound]); } } public override bool UpdateGame() { _UpdateAnimations(); return true; } private void _OnBack() { if (_ExitPopupVisible) { _ShowPopup(false); } else if (_PartyMode.GameData.NumSongsSung == 0) { _PartyMode.Back(); } else if (_PartyMode.IsFinished) { _EndParty(); } else { _ShowPopup(true); } } private void _OnSelect() { if (_ExitPopupVisible) { if (_Buttons[_ButtonPopupYes].Selected) { _EndParty(); } if (_Buttons[_ButtonPopupNo].Selected) { _ShowPopup(false); } return; } if (_Buttons[_ButtonNextRound].Selected && _Buttons[_ButtonNextRound].Visible) { _PartyMode.Next(); } if (_Buttons[_ButtonBack].Selected && _Buttons[_ButtonBack].Visible) { _PartyMode.Back(); } if (_Buttons[_ButtonExit].Selected && _Buttons[_ButtonExit].Visible) { if (_PartyMode.IsFinished) { _EndParty(); } else { _ShowPopup(true); } } } private void _EndParty() { CBase.Graphics.FadeTo(EScreen.Party); } private void _ShowPopup(bool visible) { _ExitPopupVisible = visible; _Statics[_StaticPopupBG].Visible = _ExitPopupVisible; _Texts[_TextPopupReallyExit].Visible = _ExitPopupVisible; _Buttons[_ButtonPopupYes].Visible = _ExitPopupVisible; _Buttons[_ButtonPopupNo].Visible = _ExitPopupVisible; if (_ExitPopupVisible) { _SelectElement(_Buttons[_ButtonPopupNo]); } } private static float _EaseInOut(float t) { return t < 0.5f ? 4f * t * t * t : 1f - (float)Math.Pow(-2f * t + 2f, 3) / 2f; } private static float _EaseOutBack(float t) { const float c1 = 1.70158f; const float c3 = c1 + 1f; return 1f + c3 * (float)Math.Pow(t - 1f, 3) + c1 * (float)Math.Pow(t - 1f, 2); } private string _GetName(CSwapPlayer player) { return CBase.Profiles.GetPlayerName(player.ProfileId); } private string _GetPairNames(CSwapPair pair) { return _GetName(pair.Players[0]) + " & " + _GetName(pair.Players[1]); } private void _UpdateRanking() { var ranking = _PartyMode.GetRanking(); var previous = _ShowNewResult ? _PartyMode.GameData.PreviousRanking : ranking; for (var i = 0; i < _Rows.Count; i++) { var row = _Rows[i]; var visible = i < ranking.Count; row.Player = visible ? _PartyMode.GameData.Players[i] : null; row.Avatar.Visible = visible; row.Pos.Visible = visible; row.Name.Visible = visible; row.Songs.Visible = visible; row.Average.Visible = visible; row.Highlight.Visible = false; if (!visible) { continue; } row.NewRank = ranking.IndexOf(row.Player); row.OldRank = previous.IndexOf(row.Player); if (row.OldRank < 0) { row.OldRank = row.NewRank; } row.Avatar.Texture = CBase.Profiles.GetAvatar(row.Player.ProfileId); row.Name.Text = _GetName(row.Player); row.Songs.Text = row.Player.NumSongs.ToString(); row.Average.Text = row.Player.Average.ToString("N0"); row.Pos.Text = (row.NewRank + 1) + "."; row.Highlight.Visible = row.NewRank == 0 && row.Player.NumSongs > 0; SColorF rankColor; var color = _Texts[_TextRowName].Color; if (row.Player.NumSongs > 0 && row.NewRank < _RankColors.Length && CBase.Themes.GetColor(_RankColors[row.NewRank], PartyModeId, out rankColor)) { color = rankColor; } row.Pos.Color = color; row.Name.Color = color; } } private void _PlaceRow(CRankRow row, float y) { row.Highlight.Y = y + (_Texts[_TextRowName].H - row.Highlight.H) / 2; row.Avatar.Y = y + (_Texts[_TextRowName].H - row.Avatar.H) / 2; row.Pos.Y = y; row.Name.Y = y; row.Songs.Y = y; row.Average.Y = y; } private void _UpdatePair() { var finished = _PartyMode.IsFinished; var pair = _PartyMode.CurrentPair; var showPair = !finished && pair != null; _Statics[_StaticPairAvatar2].Visible = showPair; _Texts[_TextPairName1].Visible = showPair; _Texts[_TextPairName2].Visible = showPair; _Texts[_TextAmp].Visible = showPair; _Texts[_TextTogether].Visible = showPair; _Texts[_TextPass].Visible = showPair; var pause = _PartyMode.CurrentBreak; _Texts[_TextPause].Visible = showPair && pause != null; if (pause != null) { _Texts[_TextPause].Text = CBase.Language.Translate("TR_SCREENMAIN_PAUSE", PartyModeId) + " " + _GetName(pause); } _Statics[_StaticPairAvatar1].MaxRect = _PairAvatar1Rect; _Statics[_StaticPairAvatar1].Visible = showPair || finished; if (showPair) { _Statics[_StaticPairAvatar1].Texture = CBase.Profiles.GetAvatar(pair.Players[0].ProfileId); _Statics[_StaticPairAvatar2].Texture = CBase.Profiles.GetAvatar(pair.Players[1].ProfileId); _Texts[_TextPairName1].Text = _GetName(pair.Players[0]); _Texts[_TextPairName2].Text = _GetName(pair.Players[1]); var together = _PartyMode.GetTimesTogether(pair.Players[0], pair.Players[1]); _Texts[_TextTogether].Text = together == 0 ? CBase.Language.Translate("TR_SCREENMAIN_FIRST_TIME", PartyModeId) : CBase.Language.Translate("TR_SCREENMAIN_TIMES_TOGETHER", PartyModeId).Replace("%n", (together + 1).ToString()); _Texts[_TextPass].Text = CBase.Language.Translate("TR_SCREENMAIN_PASS", PartyModeId) + " " + (_PartyMode.GameData.PassIndex + 1) + " / " + _PartyMode.GameData.Passes.Count + " · " + CBase.Language.Translate("TR_SCREENMAIN_SONG", PartyModeId) + " " + (_PartyMode.GameData.PairIndex + 1) + " / " + _PartyMode.GameData.Passes[_PartyMode.GameData.PassIndex].Count; } _Texts[_TextChampionLabel].Visible = finished; _Texts[_TextChampion].Visible = finished; _ParticleEffects[_ParticleEffectChampion].Visible = finished; if (finished) { var champion = _PartyMode.GetRanking()[0]; _Texts[_TextChampion].Text = _GetName(champion); _Statics[_StaticPairAvatar1].Texture = CBase.Profiles.GetAvatar(champion.ProfileId); var centerX = (_PairAvatar1Rect.X + _Statics[_StaticPairAvatar2].Rect.X + _Statics[_StaticPairAvatar2].Rect.W) / 2; _Statics[_StaticPairAvatar1].X = centerX - _PairAvatar1Rect.W / 2; _Statics[_StaticPairAvatar1].Y = _PairAvatar1Rect.Y + 60f; } } private void _UpdateBestPair() { var best = _PartyMode.GameData.BestPair; var visible = best != null; _Statics[_StaticBestAvatar1].Visible = visible; _Statics[_StaticBestAvatar2].Visible = visible; _Texts[_TextBestNames].Visible = visible; _Texts[_TextBestScore].Visible = visible; _Texts[_TextBestLabel].Text = _PartyMode.IsFinished ? "TR_SCREENMAIN_BEST_PAIR_FINAL" : "TR_SCREENMAIN_BEST_PAIR"; if (!visible) { return; } _Statics[_StaticBestAvatar1].Texture = CBase.Profiles.GetAvatar(best.Players[0].ProfileId); _Statics[_StaticBestAvatar2].Texture = CBase.Profiles.GetAvatar(best.Players[1].ProfileId); _Texts[_TextBestNames].Text = _GetPairNames(best); _Texts[_TextBestScore].Text = best.PairScore.ToString("N0"); } private void _UpdateLastResult() { var last = _PartyMode.GameData.LastPair; _Texts[_TextLastResult].Visible = last != null && !_PartyMode.IsFinished; _Texts[_TextHarmony].Visible = last != null && last.Bonus > 0 && !_PartyMode.IsFinished; if (last == null) { return; } _Texts[_TextLastResult].Text = CBase.Language.Translate("TR_SCREENMAIN_LAST_SONG", PartyModeId) + " " + _GetPairNames(last) + " · " + last.PairScore.ToString("N0"); _Texts[_TextHarmony].Text = CBase.Language.Translate("TR_SCREENMAIN_HARMONY_BONUS", PartyModeId) + " +" + last.Bonus; } private void _UpdateAnimations() { var time = _AnimTimer.ElapsedMilliseconds; var rankProgress = _ShowNewResult ? _EaseInOut(Math.Max(0f, Math.Min(1f, (time - _RankDelay) / _RankDuration))) : 1f; foreach (var row in _Rows) { if (row.Player == null) { continue; } var oldY = _FirstRowY + row.OldRank * _RowStep; var newY = _FirstRowY + row.NewRank * _RowStep; _PlaceRow(row, oldY + (newY - oldY) * rankProgress); } var popScale = _ShowNewResult && time < _PopDuration ? 0.3f + 0.7f * _EaseOutBack(time / _PopDuration) : 1f; _Texts[_TextLastResult].Font.Height = _LastResultHeight * popScale; _Texts[_TextHarmony].Font.Height = _HarmonyHeight * popScale; if (_PartyMode.IsFinished) { float scale; if (time < _PopDuration) { scale = 0.3f + 0.7f * _EaseOutBack(time / _PopDuration); } else { scale = 1f + 0.03f * (float)Math.Sin((time - _PopDuration) / 1000.0 * Math.PI * 1.4); } _Texts[_TextChampion].Font.Height = _ChampionHeight * scale; } } } }