2019-08-30 03:59:58 +00:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation ;
using osu.Framework.Bindables ;
using osu.Framework.Graphics ;
using osu.Framework.Graphics.Containers ;
2020-03-28 04:39:08 +00:00
using osu.Framework.Graphics.Textures ;
2019-08-30 03:59:58 +00:00
using osu.Game.Graphics ;
using osu.Game.Graphics.Sprites ;
using osu.Game.Rulesets.Objects.Drawables ;
using osu.Game.Rulesets.Osu.Objects ;
2020-11-05 05:40:48 +00:00
using osu.Game.Rulesets.Osu.Objects.Drawables ;
2019-08-30 03:59:58 +00:00
using osu.Game.Skinning ;
using osuTK ;
using osuTK.Graphics ;
2020-08-05 17:07:05 +00:00
using static osu . Game . Skinning . LegacySkinConfiguration ;
2019-08-30 03:59:58 +00:00
2020-12-04 11:21:53 +00:00
namespace osu.Game.Rulesets.Osu.Skinning.Legacy
2019-08-30 03:59:58 +00:00
{
2021-06-02 02:46:28 +00:00
public class LegacyMainCirclePiece : CompositeDrawable
2019-08-30 03:59:58 +00:00
{
2021-06-09 01:53:52 +00:00
public override bool RemoveCompletedTransforms = > false ;
2020-03-28 04:39:08 +00:00
private readonly string priorityLookup ;
2020-10-02 04:40:24 +00:00
private readonly bool hasNumber ;
2020-03-28 04:39:08 +00:00
2020-10-02 04:40:24 +00:00
public LegacyMainCirclePiece ( string priorityLookup = null , bool hasNumber = true )
2019-08-30 03:59:58 +00:00
{
2020-03-28 04:39:08 +00:00
this . priorityLookup = priorityLookup ;
2020-10-02 04:40:24 +00:00
this . hasNumber = hasNumber ;
2020-03-28 04:39:08 +00:00
2019-08-30 03:59:58 +00:00
Size = new Vector2 ( OsuHitObject . OBJECT_RADIUS * 2 ) ;
}
2021-06-04 05:51:35 +00:00
private Drawable hitCircleSprite ;
2021-09-01 10:34:57 +00:00
protected Drawable HitCircleOverlay { get ; private set ; }
2020-08-05 17:07:05 +00:00
2019-10-01 05:23:41 +00:00
private SkinnableSpriteText hitCircleText ;
2019-08-30 03:59:58 +00:00
private readonly Bindable < Color4 > accentColour = new Bindable < Color4 > ( ) ;
2019-09-26 07:57:58 +00:00
private readonly IBindable < int > indexInCurrentCombo = new Bindable < int > ( ) ;
2019-10-01 05:23:41 +00:00
2020-11-04 08:30:23 +00:00
[Resolved]
private DrawableHitObject drawableObject { get ; set ; }
2019-10-03 02:58:20 +00:00
[Resolved]
private ISkinSource skin { get ; set ; }
2019-08-30 03:59:58 +00:00
[BackgroundDependencyLoader]
2020-11-04 08:30:23 +00:00
private void load ( )
2019-08-30 03:59:58 +00:00
{
2020-11-05 05:40:48 +00:00
var drawableOsuObject = ( DrawableOsuHitObject ) drawableObject ;
2019-08-30 03:59:58 +00:00
2020-10-06 04:56:38 +00:00
bool allowFallback = false ;
// attempt lookup using priority specification
2020-10-06 05:12:46 +00:00
Texture baseTexture = getTextureWithFallback ( string . Empty ) ;
2020-10-06 04:56:38 +00:00
// if the base texture was not found without a fallback, switch on fallback mode and re-perform the lookup.
if ( baseTexture = = null )
{
allowFallback = true ;
baseTexture = getTextureWithFallback ( string . Empty ) ;
}
// at this point, any further texture fetches should be correctly using the priority source if the base texture was retrieved using it.
// the flow above handles the case where a sliderendcircle.png is retrieved from the skin, but sliderendcircleoverlay.png doesn't exist.
// expected behaviour in this scenario is not showing the overlay, rather than using hitcircleoverlay.png (potentially from the default/fall-through skin).
2020-10-06 05:12:46 +00:00
Texture overlayTexture = getTextureWithFallback ( "overlay" ) ;
2020-10-06 04:56:38 +00:00
2021-09-01 10:34:57 +00:00
InternalChildren = new [ ]
2019-08-30 03:59:58 +00:00
{
2021-09-01 10:34:57 +00:00
hitCircleSprite = new KiaiFlashingSprite
2019-08-30 03:59:58 +00:00
{
2021-09-01 10:34:57 +00:00
Texture = baseTexture ,
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
} ,
HitCircleOverlay = new KiaiFlashingSprite
{
Texture = overlayTexture ,
2019-08-30 03:59:58 +00:00
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
} ,
2020-10-02 04:40:24 +00:00
} ;
if ( hasNumber )
{
AddInternal ( hitCircleText = new SkinnableSpriteText ( new OsuSkinComponent ( OsuSkinComponents . HitCircleText ) , _ = > new OsuSpriteText
2019-08-30 03:59:58 +00:00
{
Font = OsuFont . Numeric . With ( size : 40 ) ,
UseFullGlyphHeight = false ,
2019-10-03 03:49:32 +00:00
} , confineMode : ConfineMode . NoScaling )
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
2020-10-02 04:40:24 +00:00
} ) ;
}
2019-08-30 03:59:58 +00:00
2020-03-30 10:42:18 +00:00
bool overlayAboveNumber = skin . GetConfig < OsuSkinConfiguration , bool > ( OsuSkinConfiguration . HitCircleOverlayAboveNumber ) ? . Value ? ? true ;
2020-08-05 17:07:05 +00:00
if ( overlayAboveNumber )
2021-09-01 10:34:57 +00:00
ChangeInternalChildDepth ( HitCircleOverlay , float . MinValue ) ;
2020-03-30 10:42:18 +00:00
2019-08-30 03:59:58 +00:00
accentColour . BindTo ( drawableObject . AccentColour ) ;
2020-11-05 05:40:48 +00:00
indexInCurrentCombo . BindTo ( drawableOsuObject . IndexInCurrentComboBindable ) ;
2020-03-28 04:39:08 +00:00
Texture getTextureWithFallback ( string name )
{
Texture tex = null ;
if ( ! string . IsNullOrEmpty ( priorityLookup ) )
2020-10-06 04:56:38 +00:00
{
2020-03-28 04:39:08 +00:00
tex = skin . GetTexture ( $"{priorityLookup}{name}" ) ;
2020-10-06 04:56:38 +00:00
if ( ! allowFallback )
return tex ;
}
2020-03-28 04:39:08 +00:00
return tex ? ? skin . GetTexture ( $"hitcircle{name}" ) ;
}
2019-08-30 03:59:58 +00:00
}
2020-08-05 17:07:05 +00:00
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
2020-08-25 06:16:41 +00:00
accentColour . BindValueChanged ( colour = > hitCircleSprite . Colour = LegacyColourCompatibility . DisallowZeroAlpha ( colour . NewValue ) , true ) ;
2020-10-02 04:40:24 +00:00
if ( hasNumber )
indexInCurrentCombo . BindValueChanged ( index = > hitCircleText . Text = ( index . NewValue + 1 ) . ToString ( ) , true ) ;
2021-06-02 02:32:24 +00:00
2021-06-09 07:14:55 +00:00
drawableObject . ApplyCustomUpdateState + = updateStateTransforms ;
updateStateTransforms ( drawableObject , drawableObject . State . Value ) ;
2020-08-05 17:07:05 +00:00
}
2021-06-09 07:14:55 +00:00
private void updateStateTransforms ( DrawableHitObject drawableHitObject , ArmedState state )
2019-08-30 03:59:58 +00:00
{
const double legacy_fade_duration = 240 ;
2021-06-02 02:46:28 +00:00
using ( BeginAbsoluteSequence ( drawableObject . HitStateUpdateTime ) )
2019-08-30 03:59:58 +00:00
{
2021-06-09 07:14:55 +00:00
switch ( state )
2020-11-04 08:30:23 +00:00
{
case ArmedState . Hit :
2021-09-01 10:34:57 +00:00
hitCircleSprite . FadeOut ( legacy_fade_duration , Easing . Out ) ;
hitCircleSprite . ScaleTo ( 1.4f , legacy_fade_duration , Easing . Out ) ;
HitCircleOverlay . FadeOut ( legacy_fade_duration , Easing . Out ) ;
HitCircleOverlay . ScaleTo ( 1.4f , legacy_fade_duration , Easing . Out ) ;
2020-10-02 04:40:24 +00:00
2020-11-04 08:30:23 +00:00
if ( hasNumber )
2020-10-02 04:40:24 +00:00
{
2020-11-04 08:30:23 +00:00
var legacyVersion = skin . GetConfig < LegacySetting , decimal > ( LegacySetting . Version ) ? . Value ;
if ( legacyVersion > = 2.0 m )
// legacy skins of version 2.0 and newer only apply very short fade out to the number piece.
hitCircleText . FadeOut ( legacy_fade_duration / 4 , Easing . Out ) ;
else
{
// old skins scale and fade it normally along other pieces.
hitCircleText . FadeOut ( legacy_fade_duration , Easing . Out ) ;
hitCircleText . ScaleTo ( 1.4f , legacy_fade_duration , Easing . Out ) ;
}
2020-10-02 04:40:24 +00:00
}
2019-10-03 02:58:20 +00:00
2020-11-04 08:30:23 +00:00
break ;
}
2019-08-30 03:59:58 +00:00
}
}
2021-06-09 07:14:55 +00:00
protected override void Dispose ( bool isDisposing )
{
base . Dispose ( isDisposing ) ;
if ( drawableObject ! = null )
drawableObject . ApplyCustomUpdateState - = updateStateTransforms ;
}
2019-08-30 03:59:58 +00:00
}
}