2019-01-24 08:43:03 +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.
2018-04-13 09:19:50 +00:00
2019-04-08 09:32:05 +00:00
using System.Collections.Generic ;
2020-11-20 08:28:06 +00:00
using System.Linq ;
2021-04-21 10:44:17 +00:00
using osu.Framework.Allocation ;
using osu.Framework.Bindables ;
2020-11-20 08:28:06 +00:00
using osu.Framework.Graphics ;
2018-04-13 09:19:50 +00:00
using osu.Game.Beatmaps ;
2021-04-21 10:44:17 +00:00
using osu.Game.Configuration ;
2019-04-08 09:32:05 +00:00
using osu.Game.Rulesets.Mods ;
2020-11-20 08:28:06 +00:00
using osu.Game.Rulesets.Objects.Drawables ;
using osu.Game.Rulesets.Osu.Objects.Drawables ;
2021-04-26 06:23:21 +00:00
using osu.Game.Rulesets.Osu.Skinning.Default ;
2018-04-13 09:19:50 +00:00
using osu.Game.Rulesets.Osu.UI ;
2018-09-21 06:08:43 +00:00
using osu.Game.Rulesets.UI ;
2018-11-20 07:51:59 +00:00
using osuTK ;
2018-04-13 09:19:50 +00:00
namespace osu.Game.Rulesets.Osu.Edit
{
2021-04-26 05:33:30 +00:00
public class DrawableOsuEditorRuleset : DrawableOsuRuleset
2018-04-13 09:19:50 +00:00
{
2021-06-18 12:57:04 +00:00
/// <summary>
/// Hit objects are intentionally made to fade out at a constant slower rate than in gameplay.
/// This allows a mapper to gain better historical context and use recent hitobjects as reference / snap points.
/// </summary>
public const double EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION = 700 ;
2021-04-26 05:33:30 +00:00
public DrawableOsuEditorRuleset ( Ruleset ruleset , IBeatmap beatmap , IReadOnlyList < Mod > mods )
2019-04-08 09:32:05 +00:00
: base ( ruleset , beatmap , mods )
2018-04-13 09:19:50 +00:00
{
}
2021-04-26 05:33:30 +00:00
protected override Playfield CreatePlayfield ( ) = > new OsuEditorPlayfield ( ) ;
2019-03-30 16:29:37 +00:00
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer ( ) = > new OsuPlayfieldAdjustmentContainer { Size = Vector2 . One } ;
2018-09-21 06:08:43 +00:00
2021-04-26 05:33:30 +00:00
private class OsuEditorPlayfield : OsuPlayfield
2019-03-06 03:34:58 +00:00
{
2021-04-21 10:44:17 +00:00
private Bindable < bool > hitAnimations ;
2019-03-26 04:39:19 +00:00
protected override GameplayCursorContainer CreateCursor ( ) = > null ;
2020-11-13 16:03:23 +00:00
2021-04-21 10:44:17 +00:00
[BackgroundDependencyLoader]
private void load ( OsuConfigManager config )
{
hitAnimations = config . GetBindable < bool > ( OsuSetting . EditorHitAnimations ) ;
}
2020-11-21 06:20:33 +00:00
protected override void OnNewDrawableHitObject ( DrawableHitObject d )
2020-11-20 08:28:06 +00:00
{
2020-11-21 06:20:33 +00:00
d . ApplyCustomUpdateState + = updateState ;
2020-11-20 08:28:06 +00:00
}
private void updateState ( DrawableHitObject hitObject , ArmedState state )
{
2021-04-21 10:44:17 +00:00
if ( state = = ArmedState . Idle | | hitAnimations . Value )
2020-11-20 08:28:06 +00:00
return ;
2021-04-26 06:23:21 +00:00
if ( hitObject is DrawableHitCircle circle )
2020-11-20 08:28:06 +00:00
{
2021-04-26 06:23:21 +00:00
circle . ApproachCircle
2021-06-18 12:57:04 +00:00
. FadeOutFromOne ( EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION * 4 )
2021-04-26 06:23:21 +00:00
. Expire ( ) ;
2021-04-21 10:44:17 +00:00
2021-04-26 06:23:21 +00:00
circle . ApproachCircle . ScaleTo ( 1.1f , 300 , Easing . OutQuint ) ;
}
2021-04-21 10:44:17 +00:00
2021-04-26 06:23:21 +00:00
if ( hitObject is IHasMainCirclePiece mainPieceContainer )
{
// clear any explode animation logic.
2021-06-18 13:30:45 +00:00
// this is scheduled after children to ensure that the clear happens after invocations of ApplyCustomUpdateState on the circle piece's nested skinnables.
ScheduleAfterChildren ( ( ) = >
{
if ( hitObject . HitObject = = null ) return ;
2021-06-18 13:32:51 +00:00
mainPieceContainer . CirclePiece . ApplyTransformsAt ( hitObject . StateUpdateTime , true ) ;
mainPieceContainer . CirclePiece . ClearTransformsAfter ( hitObject . StateUpdateTime , true ) ;
2021-06-18 13:30:45 +00:00
} ) ;
2021-04-26 06:23:21 +00:00
}
2021-04-21 10:44:17 +00:00
2021-04-26 06:23:21 +00:00
if ( hitObject is DrawableSliderRepeat repeat )
{
2021-06-18 13:32:51 +00:00
repeat . Arrow . ApplyTransformsAt ( hitObject . StateUpdateTime , true ) ;
repeat . Arrow . ClearTransformsAfter ( hitObject . StateUpdateTime , true ) ;
2020-11-20 08:28:06 +00:00
}
2021-04-26 06:23:21 +00:00
// adjust the visuals of top-level object types to make them stay on screen for longer than usual.
switch ( hitObject )
{
case DrawableSlider _ :
case DrawableHitCircle _ :
// Get the existing fade out transform
var existing = hitObject . Transforms . LastOrDefault ( t = > t . TargetMember = = nameof ( Alpha ) ) ;
2020-11-20 08:28:06 +00:00
2021-04-26 06:23:21 +00:00
if ( existing = = null )
return ;
2020-11-20 08:28:06 +00:00
2021-04-26 06:23:21 +00:00
hitObject . RemoveTransform ( existing ) ;
2020-11-20 08:28:06 +00:00
2021-04-26 06:23:21 +00:00
using ( hitObject . BeginAbsoluteSequence ( hitObject . HitStateUpdateTime ) )
2021-06-18 12:57:04 +00:00
hitObject . FadeOut ( EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION ) . Expire ( ) ;
2021-04-26 06:23:21 +00:00
break ;
}
2020-11-20 08:28:06 +00:00
}
2019-03-06 03:34:58 +00:00
}
2018-04-13 09:19:50 +00:00
}
}