mirror of
https://github.com/osukey/osukey.git
synced 2025-08-08 00:53:56 +09:00
Merge pull request #12580 from peppy/fix-editor-slider-repeat-animation
Fix slider repeats and tails still animating with editor hit animations disabled
This commit is contained in:
@ -11,6 +11,7 @@ using osu.Game.Configuration;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Osu.Skinning.Default;
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -56,33 +57,33 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
if (state == ArmedState.Idle || hitAnimations.Value)
|
if (state == ArmedState.Idle || hitAnimations.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// adjust the visuals of certain object types to make them stay on screen for longer than usual.
|
if (hitObject is DrawableHitCircle circle)
|
||||||
switch (hitObject)
|
|
||||||
{
|
{
|
||||||
default:
|
|
||||||
// there are quite a few drawable hit types we don't want to extend (spinners, ticks etc.)
|
|
||||||
return;
|
|
||||||
|
|
||||||
case DrawableSlider _:
|
|
||||||
// no specifics to sliders but let them fade slower below.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DrawableHitCircle circle: // also handles slider heads
|
|
||||||
circle.ApproachCircle
|
circle.ApproachCircle
|
||||||
.FadeOutFromOne(editor_hit_object_fade_out_extension * 4)
|
.FadeOutFromOne(editor_hit_object_fade_out_extension * 4)
|
||||||
.Expire();
|
.Expire();
|
||||||
|
|
||||||
circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint);
|
circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint);
|
||||||
|
|
||||||
var circlePieceDrawable = circle.CirclePiece.Drawable;
|
|
||||||
|
|
||||||
// clear any explode animation logic.
|
|
||||||
circlePieceDrawable.ApplyTransformsAt(circle.HitStateUpdateTime, true);
|
|
||||||
circlePieceDrawable.ClearTransformsAfter(circle.HitStateUpdateTime, true);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hitObject is IHasMainCirclePiece mainPieceContainer)
|
||||||
|
{
|
||||||
|
// clear any explode animation logic.
|
||||||
|
mainPieceContainer.CirclePiece.ApplyTransformsAt(hitObject.HitStateUpdateTime, true);
|
||||||
|
mainPieceContainer.CirclePiece.ClearTransformsAfter(hitObject.HitStateUpdateTime, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitObject is DrawableSliderRepeat repeat)
|
||||||
|
{
|
||||||
|
repeat.Arrow.ApplyTransformsAt(hitObject.HitStateUpdateTime, true);
|
||||||
|
repeat.Arrow.ClearTransformsAfter(hitObject.HitStateUpdateTime, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
// Get the existing fade out transform
|
||||||
var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));
|
var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));
|
||||||
|
|
||||||
@ -93,6 +94,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
|
|
||||||
using (hitObject.BeginAbsoluteSequence(hitObject.HitStateUpdateTime))
|
using (hitObject.BeginAbsoluteSequence(hitObject.HitStateUpdateTime))
|
||||||
hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
|
hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableHitCircle : DrawableOsuHitObject
|
public class DrawableHitCircle : DrawableOsuHitObject, IHasMainCirclePiece
|
||||||
{
|
{
|
||||||
public OsuAction? HitAction => HitArea.HitAction;
|
public OsuAction? HitAction => HitArea.HitAction;
|
||||||
protected virtual OsuSkinComponents CirclePieceComponent => OsuSkinComponents.HitCircle;
|
protected virtual OsuSkinComponents CirclePieceComponent => OsuSkinComponents.HitCircle;
|
||||||
|
@ -15,7 +15,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableSliderRepeat : DrawableOsuHitObject, ITrackSnaking
|
public class DrawableSliderRepeat : DrawableOsuHitObject, ITrackSnaking, IHasMainCirclePiece
|
||||||
{
|
{
|
||||||
public new SliderRepeat HitObject => (SliderRepeat)base.HitObject;
|
public new SliderRepeat HitObject => (SliderRepeat)base.HitObject;
|
||||||
|
|
||||||
@ -28,8 +28,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
public SkinnableDrawable CirclePiece { get; private set; }
|
public SkinnableDrawable CirclePiece { get; private set; }
|
||||||
|
|
||||||
|
public ReverseArrowPiece Arrow { get; private set; }
|
||||||
|
|
||||||
private Drawable scaleContainer;
|
private Drawable scaleContainer;
|
||||||
private ReverseArrowPiece arrow;
|
|
||||||
|
|
||||||
public override bool DisplayResult => false;
|
public override bool DisplayResult => false;
|
||||||
|
|
||||||
@ -57,8 +58,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
// no default for this; only visible in legacy skins.
|
// no default for this; only visible in legacy skins.
|
||||||
CirclePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderTailHitCircle), _ => Empty()),
|
CirclePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderTailHitCircle), _ => Empty())
|
||||||
arrow = new ReverseArrowPiece(),
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
Arrow = new ReverseArrowPiece(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,8 +110,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ArmedState.Hit:
|
case ArmedState.Hit:
|
||||||
this.FadeOut(animDuration, Easing.Out)
|
this.FadeOut(animDuration, Easing.Out);
|
||||||
.ScaleTo(Scale * 1.5f, animDuration, Easing.Out);
|
|
||||||
|
const float final_scale = 1.5f;
|
||||||
|
|
||||||
|
Arrow.ScaleTo(Scale * final_scale, animDuration, Easing.Out);
|
||||||
|
CirclePiece.ScaleTo(Scale * final_scale, animDuration, Easing.Out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,18 +151,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
}
|
}
|
||||||
|
|
||||||
float aimRotation = MathUtils.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X));
|
float aimRotation = MathUtils.RadiansToDegrees(MathF.Atan2(aimRotationVector.Y - Position.Y, aimRotationVector.X - Position.X));
|
||||||
while (Math.Abs(aimRotation - arrow.Rotation) > 180)
|
while (Math.Abs(aimRotation - Arrow.Rotation) > 180)
|
||||||
aimRotation += aimRotation < arrow.Rotation ? 360 : -360;
|
aimRotation += aimRotation < Arrow.Rotation ? 360 : -360;
|
||||||
|
|
||||||
if (!hasRotation)
|
if (!hasRotation)
|
||||||
{
|
{
|
||||||
arrow.Rotation = aimRotation;
|
Arrow.Rotation = aimRotation;
|
||||||
hasRotation = true;
|
hasRotation = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly).
|
// If we're already snaking, interpolate to smooth out sharp curves (linear sliders, mainly).
|
||||||
arrow.Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), arrow.Rotation, aimRotation, 0, 50, Easing.OutQuint);
|
Arrow.Rotation = Interpolation.ValueAt(Math.Clamp(Clock.ElapsedFrameTime, 0, 100), Arrow.Rotation, aimRotation, 0, 50, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||||
{
|
{
|
||||||
public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking
|
public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking, IHasMainCirclePiece
|
||||||
{
|
{
|
||||||
public new SliderTailCircle HitObject => (SliderTailCircle)base.HitObject;
|
public new SliderTailCircle HitObject => (SliderTailCircle)base.HitObject;
|
||||||
|
|
||||||
@ -35,7 +35,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
public bool Tracking { get; set; }
|
public bool Tracking { get; set; }
|
||||||
|
|
||||||
private SkinnableDrawable circlePiece;
|
public SkinnableDrawable CirclePiece { get; private set; }
|
||||||
|
|
||||||
private Container scaleContainer;
|
private Container scaleContainer;
|
||||||
|
|
||||||
public DrawableSliderTail()
|
public DrawableSliderTail()
|
||||||
@ -64,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
// no default for this; only visible in legacy skins.
|
// no default for this; only visible in legacy skins.
|
||||||
circlePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderTailHitCircle), _ => Empty())
|
CirclePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderTailHitCircle), _ => Empty())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -76,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
base.UpdateInitialTransforms();
|
base.UpdateInitialTransforms();
|
||||||
|
|
||||||
circlePiece.FadeInFromZero(HitObject.TimeFadeIn);
|
CirclePiece.FadeInFromZero(HitObject.TimeFadeIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateHitStateTransforms(ArmedState state)
|
protected override void UpdateHitStateTransforms(ArmedState state)
|
||||||
@ -85,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
Debug.Assert(HitObject.HitWindows != null);
|
Debug.Assert(HitObject.HitWindows != null);
|
||||||
|
|
||||||
(circlePiece.Drawable as IMainCirclePiece)?.Animate(state);
|
(CirclePiece.Drawable as IMainCirclePiece)?.Animate(state);
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
// 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.Skinning;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Skinning.Default
|
||||||
|
{
|
||||||
|
public interface IHasMainCirclePiece
|
||||||
|
{
|
||||||
|
SkinnableDrawable CirclePiece { get; }
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user