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 ;
using osu.Framework.Graphics.Sprites ;
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 ;
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
namespace osu.Game.Rulesets.Osu.Skinning
{
public class LegacyMainCirclePiece : CompositeDrawable
{
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 ) ;
}
2020-08-05 20:45:00 +00:00
private Container < Sprite > circleSprites ;
2020-08-07 07:36:40 +00:00
private Sprite hitCircleSprite ;
private Sprite hitCircleOverlay ;
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 IBindable < ArmedState > state = new Bindable < ArmedState > ( ) ;
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
2019-10-03 02:58:20 +00:00
[Resolved]
private ISkinSource skin { get ; set ; }
2019-08-30 03:59:58 +00:00
[BackgroundDependencyLoader]
2019-10-15 19:28:50 +00:00
private void load ( DrawableHitObject drawableObject )
2019-08-30 03:59:58 +00:00
{
2019-09-26 07:57:58 +00:00
OsuHitObject osuObject = ( OsuHitObject ) drawableObject . HitObject ;
2019-08-30 03:59:58 +00:00
2020-10-06 04:56:38 +00:00
Texture baseTexture ;
Texture overlayTexture ;
bool allowFallback = false ;
// attempt lookup using priority specification
baseTexture = getTextureWithFallback ( string . Empty ) ;
// 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).
overlayTexture = getTextureWithFallback ( "overlay" ) ;
2019-08-30 03:59:58 +00:00
InternalChildren = new Drawable [ ]
{
2020-08-05 20:45:00 +00:00
circleSprites = new Container < Sprite >
2019-08-30 03:59:58 +00:00
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
2020-08-05 17:07:05 +00:00
RelativeSizeAxes = Axes . Both ,
Children = new [ ]
{
hitCircleSprite = new Sprite
{
2020-10-06 04:56:38 +00:00
Texture = baseTexture ,
2020-08-05 17:07:05 +00:00
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
} ,
hitCircleOverlay = new Sprite
{
2020-10-06 04:56:38 +00:00
Texture = overlayTexture ,
2020-08-05 17:07:05 +00:00
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
}
}
2019-08-30 03:59:58 +00:00
} ,
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 )
AddInternal ( hitCircleOverlay . CreateProxy ( ) ) ;
2020-03-30 10:42:18 +00:00
2019-08-30 03:59:58 +00:00
state . BindTo ( drawableObject . State ) ;
accentColour . BindTo ( drawableObject . AccentColour ) ;
2019-09-26 07:57:58 +00:00
indexInCurrentCombo . BindTo ( osuObject . 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 ( ) ;
state . BindValueChanged ( updateState , true ) ;
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 ) ;
2020-08-05 17:07:05 +00:00
}
2019-08-30 03:59:58 +00:00
private void updateState ( ValueChangedEvent < ArmedState > state )
{
const double legacy_fade_duration = 240 ;
switch ( state . NewValue )
{
case ArmedState . Hit :
2020-08-05 20:45:00 +00:00
circleSprites . FadeOut ( legacy_fade_duration , Easing . Out ) ;
circleSprites . ScaleTo ( 1.4f , legacy_fade_duration , Easing . Out ) ;
2020-08-05 17:07:05 +00:00
2020-10-02 04:40:24 +00:00
if ( hasNumber )
2020-08-05 17:07:05 +00:00
{
2020-10-02 04:40:24 +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-08-05 17:07:05 +00:00
}
2019-10-03 02:58:20 +00:00
2019-08-30 03:59:58 +00:00
break ;
}
}
}
}