1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 15:03:13 +08:00

Align legacy followcircle anims to slider ticks

This commit is contained in:
Alden Wu 2022-07-19 02:08:53 -07:00
parent e346624b14
commit d213f56f79
4 changed files with 119 additions and 51 deletions

View File

@ -1,8 +1,6 @@
// 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 System.Diagnostics;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@ -32,37 +30,31 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default
};
}
protected override void OnTrackingChanged(ValueChangedEvent<bool> tracking)
protected override void OnSliderPress()
{
Debug.Assert(ParentObject != null);
const float duration = 300f;
if (ParentObject.Judged)
return;
if (tracking.NewValue)
{
if (Precision.AlmostEquals(0, Alpha))
this.ScaleTo(1);
this.ScaleTo(DrawableSliderBall.FOLLOW_AREA, duration, Easing.OutQuint)
.FadeTo(1f, duration, Easing.OutQuint);
}
else
{
this.ScaleTo(DrawableSliderBall.FOLLOW_AREA * 1.2f, duration / 2, Easing.OutQuint)
.FadeTo(0, duration / 2, Easing.OutQuint);
}
.FadeIn(duration, Easing.OutQuint);
}
protected override void OnSliderEnd()
protected override void OnSliderRelease()
{
const float fade_duration = 300;
const float duration = 150;
// intentionally pile on an extra FadeOut to make it happen much faster
this.ScaleTo(1, fade_duration, Easing.OutQuint);
this.FadeOut(fade_duration / 2, Easing.OutQuint);
this.ScaleTo(DrawableSliderBall.FOLLOW_AREA * 1.2f, duration, Easing.OutQuint)
.FadeTo(0, duration, Easing.OutQuint);
}
protected override void OnSliderTail()
{
const float duration = 300;
this.ScaleTo(1, duration, Easing.OutQuint)
.FadeOut(duration / 2, Easing.OutQuint);
}
}
}

View File

@ -1,8 +1,8 @@
// 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 System.Diagnostics;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects.Drawables;
@ -23,7 +23,17 @@ namespace osu.Game.Rulesets.Osu.Skinning
[BackgroundDependencyLoader]
private void load()
{
((DrawableSlider?)ParentObject)?.Tracking.BindValueChanged(OnTrackingChanged, true);
((DrawableSlider?)ParentObject)?.Tracking.BindValueChanged(tracking =>
{
Debug.Assert(ParentObject != null);
if (ParentObject.Judged)
return;
if (tracking.NewValue)
OnSliderPress();
else
OnSliderRelease();
}, true);
}
protected override void LoadComplete()
@ -48,13 +58,18 @@ namespace osu.Game.Rulesets.Osu.Skinning
private void updateStateTransforms(DrawableHitObject drawableObject, ArmedState state)
{
// Gets called by slider ticks, tails, etc., leading to duplicated
// animations which may negatively affect performance
if (drawableObject is not DrawableSlider)
return;
using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime))
OnSliderEnd();
{
switch (state)
{
case ArmedState.Hit:
OnSliderTail();
break;
}
}
}
protected override void Dispose(bool isDisposing)
@ -68,8 +83,10 @@ namespace osu.Game.Rulesets.Osu.Skinning
}
}
protected abstract void OnTrackingChanged(ValueChangedEvent<bool> tracking);
protected abstract void OnSliderPress();
protected abstract void OnSliderEnd();
protected abstract void OnSliderRelease();
protected abstract void OnSliderTail();
}
}

View File

@ -3,12 +3,11 @@
using System;
using System.Diagnostics;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
namespace osu.Game.Rulesets.Osu.Skinning.Legacy
{
public class LegacyFollowCircle : FollowCircle
public class LegacyFollowCircle : TickFollowCircle
{
public LegacyFollowCircle(Drawable animationContent)
{
@ -21,35 +20,37 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
InternalChild = animationContent;
}
protected override void OnTrackingChanged(ValueChangedEvent<bool> tracking)
protected override void OnSliderPress()
{
Debug.Assert(ParentObject != null);
if (ParentObject.Judged)
return;
double remainingTime = Math.Max(0, ParentObject.HitStateUpdateTime - Time.Current);
// Note that the scale adjust here is 2 instead of DrawableSliderBall.FOLLOW_AREA to match legacy behaviour.
// This means the actual tracking area for gameplay purposes is larger than the sprite (but skins may be accounting for this).
if (tracking.NewValue)
{
// TODO: Follow circle should bounce on each slider tick.
this.ScaleTo(0.5f).ScaleTo(2f, Math.Min(180f, remainingTime), Easing.Out)
.FadeTo(0).FadeTo(1f, Math.Min(60f, remainingTime));
}
else
{
// TODO: Should animate only at the next slider tick if we want to match stable perfectly.
this.ScaleTo(4f, 100)
.FadeTo(0f, 100);
}
}
protected override void OnSliderEnd()
protected override void OnSliderTail()
{
this.ScaleTo(1.6f, 200, Easing.Out)
.FadeOut(200, Easing.In);
}
protected override void OnSliderTick()
{
// TODO: Follow circle should bounce on each slider tick.
// TEMP DUMMY ANIMS
this.ScaleTo(2.2f)
.ScaleTo(2f, 175f);
}
protected override void OnSliderBreak()
{
this.ScaleTo(4f, 100)
.FadeTo(0f, 100);
}
}
}

View File

@ -0,0 +1,58 @@
// 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.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Skinning
{
public abstract class TickFollowCircle : FollowCircle
{
protected override void LoadComplete()
{
base.LoadComplete();
if (ParentObject != null)
ParentObject.ApplyCustomUpdateState += updateStateTransforms;
}
private void updateStateTransforms(DrawableHitObject drawableObject, ArmedState state)
{
using (BeginAbsoluteSequence(drawableObject.HitStateUpdateTime))
{
switch (state)
{
case ArmedState.Hit:
if (drawableObject is DrawableSliderTick or DrawableSliderRepeat)
OnSliderTick();
break;
case ArmedState.Miss:
if (drawableObject is DrawableSlider or DrawableSliderTick or DrawableSliderRepeat)
OnSliderBreak();
break;
}
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (ParentObject != null)
ParentObject.ApplyCustomUpdateState -= updateStateTransforms;
}
/// <summary>
/// Sealed empty. Override <see cref="OnSliderBreak" /> instead, since animations
/// should only play on slider ticks.
/// </summary>
protected sealed override void OnSliderRelease()
{
}
protected abstract void OnSliderTick();
protected abstract void OnSliderBreak();
}
}