// Copyright (c) ppy Pty Ltd . 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; using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking, ITrackSnaking { private readonly Slider slider; /// /// The judgement text is provided by the . /// public override bool DisplayResult => false; public bool Tracking { get; set; } private readonly IBindable scaleBindable = new BindableFloat(); private readonly SkinnableDrawable circlePiece; private readonly Container scaleContainer; public DrawableSliderTail(Slider slider, SliderTailCircle hitCircle) : base(hitCircle) { this.slider = slider; Origin = Anchor.Centre; Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); InternalChildren = new Drawable[] { scaleContainer = new Container { RelativeSizeAxes = Axes.Both, Origin = Anchor.Centre, Anchor = Anchor.Centre, Children = new Drawable[] { // no default for this; only visible in legacy skins. circlePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderTailHitCircle), _ => Empty()) } }, }; } [BackgroundDependencyLoader] private void load() { scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); scaleBindable.BindTo(HitObject.ScaleBindable); } protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); circlePiece.FadeInFromZero(HitObject.TimeFadeIn); } protected override void UpdateStateTransforms(ArmedState state) { base.UpdateStateTransforms(state); Debug.Assert(HitObject.HitWindows != null); switch (state) { case ArmedState.Idle: this.Delay(HitObject.TimePreempt).FadeOut(500); Expire(true); break; case ArmedState.Miss: this.FadeOut(100); break; case ArmedState.Hit: // todo: temporary / arbitrary this.Delay(800).FadeOut(); break; } } protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered && timeOffset >= 0) ApplyResult(r => r.Type = Tracking ? r.Judgement.MaxResult : r.Judgement.MinResult); } public void UpdateSnakingPosition(Vector2 start, Vector2 end) { Position = end; } } }