2023-09-13 17:51:31 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2022-02-20 22:48:33 +08:00
// See the LICENCE file in the repository root for full licence text.
2023-09-13 17:51:31 +08:00
using System ;
using osu.Framework.Allocation ;
using osu.Framework.Bindables ;
using osu.Framework.Extensions.LocalisationExtensions ;
using osu.Framework.Graphics ;
using osu.Framework.Graphics.UserInterface ;
2022-02-20 23:02:46 +08:00
using osu.Framework.Localisation ;
2023-09-13 17:51:31 +08:00
using osu.Game.Graphics ;
using osu.Game.Graphics.Sprites ;
using osu.Game.Graphics.UserInterface ;
2022-05-07 16:48:15 +08:00
using osu.Game.Localisation ;
2023-09-13 17:51:31 +08:00
using osu.Game.Rulesets.Mods ;
using osuTK ;
2022-02-20 22:48:33 +08:00
namespace osu.Game.Overlays.Mods
{
2023-09-13 17:51:31 +08:00
/// <summary>
2023-09-13 17:55:17 +08:00
/// On the mod select overlay, this provides a local updating view of the aggregate score multiplier coming from mods.
2023-09-13 17:51:31 +08:00
/// </summary>
2023-09-13 18:33:39 +08:00
public partial class DifficultyMultiplierDisplay : ModFooterInformationDisplay , IHasCurrentValue < double >
2022-02-20 22:48:33 +08:00
{
2023-09-13 17:51:31 +08:00
public const float HEIGHT = 42 ;
public Bindable < double > Current
{
get = > current . Current ;
set = > current . Current = value ;
}
private readonly BindableWithCurrent < double > current = new BindableWithCurrent < double > ( ) ;
2023-09-13 18:33:39 +08:00
private const float transition_duration = 200 ;
private RollingCounter < double > counter = null ! ;
2023-09-13 17:51:31 +08:00
[Resolved]
private OsuColour colours { get ; set ; } = null ! ;
[Resolved]
private OverlayColourProvider colourProvider { get ; set ; } = null ! ;
2022-02-20 22:48:33 +08:00
public DifficultyMultiplierDisplay ( )
{
2022-08-30 03:48:45 +08:00
Current . Default = 1d ;
Current . Value = 1d ;
2023-09-13 17:51:31 +08:00
}
[BackgroundDependencyLoader]
private void load ( )
{
2023-09-13 18:33:39 +08:00
LeftContent . AddRange ( new Drawable [ ]
{
new OsuSpriteText
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
Shear = new Vector2 ( - ShearedOverlayContainer . SHEAR , 0 ) ,
Text = DifficultyMultiplierDisplayStrings . DifficultyMultiplier ,
Font = OsuFont . Default . With ( size : 17 , weight : FontWeight . SemiBold )
}
} ) ;
2023-09-13 17:51:31 +08:00
2023-09-13 18:33:39 +08:00
RightContent . Add ( counter = new EffectCounter
{
Margin = new MarginPadding ( 10 ) ,
AutoSizeAxes = Axes . Y ,
Width = 40 ,
Shear = new Vector2 ( - ShearedOverlayContainer . SHEAR , 0 ) ,
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
Current = { BindTarget = Current }
} ) ;
2022-02-20 22:48:33 +08:00
}
protected override void LoadComplete ( )
{
2023-09-13 18:33:39 +08:00
base . LoadComplete ( ) ;
2023-09-13 17:51:31 +08:00
Current . BindValueChanged ( e = >
{
2023-09-13 17:55:17 +08:00
var effect = calculateEffectForComparison ( e . NewValue . CompareTo ( Current . Default ) ) ;
2023-09-13 17:51:31 +08:00
setColours ( effect ) ;
} , true ) ;
2022-04-05 17:25:27 +08:00
2022-03-08 06:11:20 +08:00
// required to prevent the counter initially rolling up from 0 to 1
// due to `Current.Value` having a nonstandard default value of 1.
2023-09-13 17:55:17 +08:00
counter . SetCountWithoutRolling ( Current . Value ) ;
2022-02-20 23:02:46 +08:00
}
2023-09-13 17:51:31 +08:00
/// <summary>
/// Fades colours of text and its background according to displayed value.
/// </summary>
/// <param name="effect">Effect of the value.</param>
private void setColours ( ModEffect effect )
{
switch ( effect )
{
case ModEffect . NotChanged :
2023-09-13 18:33:39 +08:00
MainBackground . FadeColour ( colourProvider . Background4 , transition_duration , Easing . OutQuint ) ;
counter . FadeColour ( Colour4 . White , transition_duration , Easing . OutQuint ) ;
2023-09-13 17:51:31 +08:00
break ;
case ModEffect . DifficultyReduction :
2023-09-13 18:33:39 +08:00
MainBackground . FadeColour ( colours . ForModType ( ModType . DifficultyReduction ) , transition_duration , Easing . OutQuint ) ;
counter . FadeColour ( colourProvider . Background5 , transition_duration , Easing . OutQuint ) ;
2023-09-13 17:51:31 +08:00
break ;
case ModEffect . DifficultyIncrease :
2023-09-13 18:33:39 +08:00
MainBackground . FadeColour ( colours . ForModType ( ModType . DifficultyIncrease ) , transition_duration , Easing . OutQuint ) ;
counter . FadeColour ( colourProvider . Background5 , transition_duration , Easing . OutQuint ) ;
2023-09-13 17:51:31 +08:00
break ;
default :
throw new ArgumentOutOfRangeException ( nameof ( effect ) ) ;
}
}
/// <summary>
/// Converts signed integer into <see cref="ModEffect"/>. Negative values are counted as difficulty reduction, positive as increase.
/// </summary>
/// <param name="comparison">Value to convert. Will arrive from comparison between <see cref="Current"/> bindable once it changes and it's <see cref="Bindable{T}.Default"/>.</param>
/// <returns>Effect of the value.</returns>
2023-09-13 17:55:17 +08:00
private static ModEffect calculateEffectForComparison ( int comparison )
2023-09-13 17:51:31 +08:00
{
if ( comparison = = 0 )
return ModEffect . NotChanged ;
if ( comparison < 0 )
return ModEffect . DifficultyReduction ;
return ModEffect . DifficultyIncrease ;
}
protected enum ModEffect
{
NotChanged ,
DifficultyReduction ,
DifficultyIncrease
}
private partial class EffectCounter : RollingCounter < double >
{
protected override double RollingDuration = > 500 ;
2023-09-13 18:33:39 +08:00
protected override LocalisableString FormatCount ( double count ) = > count . ToLocalisableString ( @"0.00x" ) ;
2023-09-13 17:51:31 +08:00
protected override OsuSpriteText CreateSpriteText ( ) = > new OsuSpriteText
{
2023-09-13 18:33:39 +08:00
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
2023-09-13 17:51:31 +08:00
Font = OsuFont . Default . With ( size : 17 , weight : FontWeight . SemiBold )
} ;
}
2022-02-20 22:48:33 +08:00
}
}