2019-08-30 11:59:58 +08: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 ;
2021-12-28 22:50:43 +08:00
using osu.Framework.Graphics.Sprites ;
2020-03-28 12:39:08 +08:00
using osu.Framework.Graphics.Textures ;
2019-08-30 11:59:58 +08: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 13:40:48 +08:00
using osu.Game.Rulesets.Osu.Objects.Drawables ;
2019-08-30 11:59:58 +08:00
using osu.Game.Skinning ;
using osuTK ;
using osuTK.Graphics ;
2020-12-04 19:21:53 +08:00
namespace osu.Game.Rulesets.Osu.Skinning.Legacy
2019-08-30 11:59:58 +08:00
{
2021-06-02 10:46:28 +08:00
public class LegacyMainCirclePiece : CompositeDrawable
2019-08-30 11:59:58 +08:00
{
2021-06-09 09:53:52 +08:00
public override bool RemoveCompletedTransforms = > false ;
2020-03-28 12:39:08 +08:00
private readonly string priorityLookup ;
2020-10-02 12:40:24 +08:00
private readonly bool hasNumber ;
2020-03-28 12:39:08 +08:00
2020-10-02 12:40:24 +08:00
public LegacyMainCirclePiece ( string priorityLookup = null , bool hasNumber = true )
2019-08-30 11:59:58 +08:00
{
2020-03-28 12:39:08 +08:00
this . priorityLookup = priorityLookup ;
2020-10-02 12:40:24 +08:00
this . hasNumber = hasNumber ;
2020-03-28 12:39:08 +08:00
2019-08-30 11:59:58 +08:00
Size = new Vector2 ( OsuHitObject . OBJECT_RADIUS * 2 ) ;
}
2021-06-04 13:51:35 +08:00
private Drawable hitCircleSprite ;
2021-09-01 18:34:57 +08:00
2021-10-04 01:14:01 +08:00
protected Container OverlayLayer { get ; private set ; }
2020-08-06 01:07:05 +08:00
2021-10-03 21:40:32 +08:00
private Drawable hitCircleOverlay ;
2019-10-01 13:23:41 +08:00
private SkinnableSpriteText hitCircleText ;
2019-08-30 11:59:58 +08:00
private readonly Bindable < Color4 > accentColour = new Bindable < Color4 > ( ) ;
2019-09-26 15:57:58 +08:00
private readonly IBindable < int > indexInCurrentCombo = new Bindable < int > ( ) ;
2019-10-01 13:23:41 +08:00
2020-11-04 16:30:23 +08:00
[Resolved]
private DrawableHitObject drawableObject { get ; set ; }
2019-10-03 10:58:20 +08:00
[Resolved]
private ISkinSource skin { get ; set ; }
2019-08-30 11:59:58 +08:00
[BackgroundDependencyLoader]
2020-11-04 16:30:23 +08:00
private void load ( )
2019-08-30 11:59:58 +08:00
{
2020-11-05 13:40:48 +08:00
var drawableOsuObject = ( DrawableOsuHitObject ) drawableObject ;
2019-08-30 11:59:58 +08:00
2020-10-06 12:56:38 +08:00
bool allowFallback = false ;
// attempt lookup using priority specification
2020-10-06 13:12:46 +08:00
Texture baseTexture = getTextureWithFallback ( string . Empty ) ;
2020-10-06 12:56:38 +08: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).
2021-09-01 18:34:57 +08:00
InternalChildren = new [ ]
2019-08-30 11:59:58 +08:00
{
2021-12-28 22:50:43 +08:00
hitCircleSprite = new KiaiFlashingDrawable ( ( ) = > new Sprite { Texture = baseTexture } )
2019-08-30 11:59:58 +08:00
{
2021-09-01 18:34:57 +08:00
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
} ,
2021-10-03 21:40:32 +08:00
OverlayLayer = new Container
2021-09-01 18:34:57 +08:00
{
2019-08-30 11:59:58 +08:00
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
2021-12-28 22:53:54 +08:00
Child = hitCircleOverlay = new KiaiFlashingDrawable ( ( ) = > getAnimationWithFallback ( @"overlay" , 1000 / 2d ) )
2021-10-03 21:40:32 +08:00
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
} ,
}
2020-10-02 12:40:24 +08:00
} ;
if ( hasNumber )
{
2021-10-03 21:40:32 +08:00
OverlayLayer . Add ( hitCircleText = new SkinnableSpriteText ( new OsuSkinComponent ( OsuSkinComponents . HitCircleText ) , _ = > new OsuSpriteText
2019-08-30 11:59:58 +08:00
{
Font = OsuFont . Numeric . With ( size : 40 ) ,
UseFullGlyphHeight = false ,
2019-10-03 11:49:32 +08:00
} , confineMode : ConfineMode . NoScaling )
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
2020-10-02 12:40:24 +08:00
} ) ;
}
2019-08-30 11:59:58 +08:00
2020-03-30 18:42:18 +08:00
bool overlayAboveNumber = skin . GetConfig < OsuSkinConfiguration , bool > ( OsuSkinConfiguration . HitCircleOverlayAboveNumber ) ? . Value ? ? true ;
2020-08-06 01:07:05 +08:00
if ( overlayAboveNumber )
2021-10-03 21:40:32 +08:00
OverlayLayer . ChangeChildDepth ( hitCircleOverlay , float . MinValue ) ;
2020-03-30 18:42:18 +08:00
2019-08-30 11:59:58 +08:00
accentColour . BindTo ( drawableObject . AccentColour ) ;
2020-11-05 13:40:48 +08:00
indexInCurrentCombo . BindTo ( drawableOsuObject . IndexInCurrentComboBindable ) ;
2020-03-28 12:39:08 +08:00
Texture getTextureWithFallback ( string name )
{
Texture tex = null ;
if ( ! string . IsNullOrEmpty ( priorityLookup ) )
2020-10-06 12:56:38 +08:00
{
2020-03-28 12:39:08 +08:00
tex = skin . GetTexture ( $"{priorityLookup}{name}" ) ;
2020-10-06 12:56:38 +08:00
if ( ! allowFallback )
return tex ;
}
2020-03-28 12:39:08 +08:00
return tex ? ? skin . GetTexture ( $"hitcircle{name}" ) ;
}
2021-12-28 22:53:54 +08:00
Drawable getAnimationWithFallback ( string name , double frameLength )
{
Drawable animation = null ;
if ( ! string . IsNullOrEmpty ( priorityLookup ) )
{
animation = skin . GetAnimation ( $"{priorityLookup}{name}" , true , true , frameLength : frameLength ) ;
if ( ! allowFallback )
return animation ;
}
return animation ? ? skin . GetAnimation ( $"hitcircle{name}" , true , true , frameLength : frameLength ) ;
}
2019-08-30 11:59:58 +08:00
}
2020-08-06 01:07:05 +08:00
protected override void LoadComplete ( )
{
base . LoadComplete ( ) ;
2020-08-25 14:16:41 +08:00
accentColour . BindValueChanged ( colour = > hitCircleSprite . Colour = LegacyColourCompatibility . DisallowZeroAlpha ( colour . NewValue ) , true ) ;
2020-10-02 12:40:24 +08:00
if ( hasNumber )
indexInCurrentCombo . BindValueChanged ( index = > hitCircleText . Text = ( index . NewValue + 1 ) . ToString ( ) , true ) ;
2021-06-02 10:32:24 +08:00
2021-06-09 15:14:55 +08:00
drawableObject . ApplyCustomUpdateState + = updateStateTransforms ;
updateStateTransforms ( drawableObject , drawableObject . State . Value ) ;
2020-08-06 01:07:05 +08:00
}
2021-06-09 15:14:55 +08:00
private void updateStateTransforms ( DrawableHitObject drawableHitObject , ArmedState state )
2019-08-30 11:59:58 +08:00
{
const double legacy_fade_duration = 240 ;
2021-06-02 10:46:28 +08:00
using ( BeginAbsoluteSequence ( drawableObject . HitStateUpdateTime ) )
2019-08-30 11:59:58 +08:00
{
2021-06-09 15:14:55 +08:00
switch ( state )
2020-11-04 16:30:23 +08:00
{
case ArmedState . Hit :
2021-09-01 18:34:57 +08:00
hitCircleSprite . FadeOut ( legacy_fade_duration , Easing . Out ) ;
hitCircleSprite . ScaleTo ( 1.4f , legacy_fade_duration , Easing . Out ) ;
2021-10-03 21:40:32 +08:00
hitCircleOverlay . FadeOut ( legacy_fade_duration , Easing . Out ) ;
hitCircleOverlay . ScaleTo ( 1.4f , legacy_fade_duration , Easing . Out ) ;
2020-10-02 12:40:24 +08:00
2020-11-04 16:30:23 +08:00
if ( hasNumber )
2020-10-02 12:40:24 +08:00
{
2021-10-28 05:24:20 +08:00
decimal? legacyVersion = skin . GetConfig < SkinConfiguration . LegacySetting , decimal > ( SkinConfiguration . LegacySetting . Version ) ? . Value ;
2020-11-04 16:30:23 +08:00
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 12:40:24 +08:00
}
2019-10-03 10:58:20 +08:00
2020-11-04 16:30:23 +08:00
break ;
}
2019-08-30 11:59:58 +08:00
}
}
2021-06-09 15:14:55 +08:00
protected override void Dispose ( bool isDisposing )
{
base . Dispose ( isDisposing ) ;
if ( drawableObject ! = null )
drawableObject . ApplyCustomUpdateState - = updateStateTransforms ;
}
2019-08-30 11:59:58 +08:00
}
}