Example #1
0
        protected virtual void ApplyCustomState(DrawableHitObject drawable, ArmedState state)
        {
            var h = (OsuHitObject)drawable.HitObject;

            // apply grow effect
            switch (drawable)
            {
            case DrawableSliderHead _:
            case DrawableSliderTail _:
                // special cases we should *not* be scaling.
                break;

            case DrawableSlider _:
            case DrawableHitCircle _:
            {
                using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt))
                    drawable.ScaleTo(StartScale).Then().ScaleTo(EndScale, h.TimePreempt, Easing.OutSine);
                break;
            }
            }

            // remove approach circles
            switch (drawable)
            {
            case DrawableHitCircle circle:
                // we don't want to see the approach circle
                using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt))
                    circle.ApproachCircle.Hide();
                break;
            }
        }
        private void applyTransform(DrawableHitObject drawable, ArmedState state)
        {
            switch (drawable)
            {
            case DrawableSliderHead _:
            case DrawableSliderTail _:
            case DrawableSliderTick _:
            case DrawableSliderRepeat _:
                return;

            default:
                var hitObject = (OsuHitObject)drawable.HitObject;

                float appearDistance = (float)(hitObject.TimePreempt - hitObject.TimeFadeIn) / 2;

                Vector2 originalPosition = drawable.Position;
                Vector2 appearOffset     = new Vector2(MathF.Cos(theta), MathF.Sin(theta)) * appearDistance;

                // the - 1 and + 1 prevents the hit objects to appear in the wrong position.
                double appearTime   = hitObject.StartTime - hitObject.TimePreempt - 1;
                double moveDuration = hitObject.TimePreempt + 1;

                using (drawable.BeginAbsoluteSequence(appearTime, true))
                {
                    drawable
                    .MoveToOffset(appearOffset)
                    .MoveTo(originalPosition, moveDuration, Easing.InOutSine);
                }

                theta += (float)hitObject.TimeFadeIn / 1000;
                break;
            }
        }
Example #3
0
        protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state)
        {
            if (!(drawable is DrawableOsuHitObject d))
                return;

            var fadeOutStartTime = d.HitObject.StartTime - preEmpt + d.FadeInDuration;
            var fadeOutDuration = preEmpt * fade_out_duration_multiplier;

            // new duration from completed fade in to end (before fading out)
            var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime;

            switch (drawable)
            {
                case DrawableHitCircle circle:
                    // we don't want to see the approach circle
                    circle.ApproachCircle.Hide();

                    // fade out immediately after fade in.
                    using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
                        circle.FadeOut(fadeOutDuration);
                    break;
                case DrawableSlider slider:
                    using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
                    {
                        slider.Body.FadeOut(longFadeDuration, Easing.Out);

                        // delay a bit less to let the sliderball fade out peacefully instead of having a hard cut
                        using (slider.BeginDelayedSequence(longFadeDuration - fadeOutDuration, true))
                            slider.Ball.FadeOut(fadeOutDuration);
                    }

                    break;
                case DrawableSpinner spinner:
                    // hide elements we don't care about.
                    spinner.Disc.Hide();
                    spinner.Ticks.Hide();
                    spinner.Background.Hide();

                    using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true))
                    {
                        spinner.FadeOut(fadeOutDuration);

                        // speed up the end sequence accordingly
                        switch (state)
                        {
                            case ArmedState.Hit:
                                spinner.ScaleTo(spinner.Scale * 1.2f, fadeOutDuration * 2, Easing.Out);
                                break;
                            case ArmedState.Miss:
                                spinner.ScaleTo(spinner.Scale * 0.8f, fadeOutDuration * 2, Easing.In);
                                break;
                        }

                        spinner.Expire();
                    }

                    break;
            }
        }
Example #4
0
            private void updateState(DrawableHitObject hitObject, ArmedState state)
            {
                if (state == ArmedState.Idle || hitAnimations.Value)
                {
                    return;
                }

                if (hitObject is DrawableHitCircle circle)
                {
                    circle.ApproachCircle
                    .FadeOutFromOne(EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION * 4)
                    .Expire();

                    circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint);
                }

                if (hitObject is IHasMainCirclePiece mainPieceContainer)
                {
                    // clear any explode animation logic.
                    // 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;
                        }

                        mainPieceContainer.CirclePiece.ApplyTransformsAt(hitObject.StateUpdateTime, true);
                        mainPieceContainer.CirclePiece.ClearTransformsAfter(hitObject.StateUpdateTime, true);
                    });
                }

                if (hitObject is DrawableSliderRepeat repeat)
                {
                    repeat.Arrow.ApplyTransformsAt(hitObject.StateUpdateTime, true);
                    repeat.Arrow.ClearTransformsAfter(hitObject.StateUpdateTime, 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
                    var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));

                    if (existing == null)
                    {
                        return;
                    }

                    hitObject.RemoveTransform(existing);

                    using (hitObject.BeginAbsoluteSequence(hitObject.HitStateUpdateTime))
                        hitObject.FadeOut(EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION).Expire();
                    break;
                }
            }
Example #5
0
        private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state)
        {
            var     osuObject = (OsuHitObject)drawable.HitObject;
            Vector2 origin    = drawable.Position;

            // Wiggle the repeat points and the tail with the slider instead of independently.
            // Also fixes an issue with repeat points being positioned incorrectly.
            if (osuObject is SliderRepeat || osuObject is SliderTailCircle)
            {
                return;
            }

            Random objRand = new Random((int)osuObject.StartTime);

            // Wiggle all objects during TimePreempt
            int amountWiggles = (int)osuObject.TimePreempt / wiggle_duration;

            void wiggle()
            {
                float nextAngle = (float)(objRand.NextDouble() * 2 * Math.PI);
                float nextDist  = (float)(objRand.NextDouble() * wiggle_strength);

                drawable.MoveTo(new Vector2((float)(nextDist * Math.Cos(nextAngle) + origin.X), (float)(nextDist * Math.Sin(nextAngle) + origin.Y)), wiggle_duration);
            }

            for (int i = 0; i < amountWiggles; i++)
            {
                using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration))
                    wiggle();
            }

            // Keep wiggling sliders and spinners for their duration
            if (!(osuObject is IHasDuration endTime))
            {
                return;
            }

            amountWiggles = (int)(endTime.Duration / wiggle_duration);

            for (int i = 0; i < amountWiggles; i++)
            {
                using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration))
                    wiggle();
            }
        }
Example #6
0
 private void dropOffScreen(DrawableHitObject obj, double failTime, float randomRotation, Vector2 originalScale, Vector2 originalPosition)
 {
     using (obj.BeginAbsoluteSequence(failTime))
     {
         obj.RotateTo(randomRotation, duration);
         obj.ScaleTo(originalScale * 0.5f, duration);
         obj.MoveTo(originalPosition + new Vector2(0, 400), duration);
     }
 }
        protected override void ApplyHiddenState(DrawableHitObject o, ArmedState state)
        {
            const float hiddenTime = 2000f;

            var    ho    = o.HitObject;
            double start = ho.StartTime - hiddenTime;

            using (o.BeginAbsoluteSequence(start, true))
                o.FadeOut(hiddenTime);
        }
Example #8
0
        protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state)
        {
            if (!(drawable is DrawableOsuHitObject d))
            {
                return;
            }

            var h = d.HitObject;

            var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadein;
            var fadeOutDuration  = h.TimePreempt * fade_out_duration_multiplier;

            // new duration from completed fade in to end (before fading out)
            var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime;

            switch (drawable)
            {
            case DrawableHitCircle circle:
                // we don't want to see the approach circle
                using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true))
                    circle.ApproachCircle.Hide();

                // fade out immediately after fade in.
                using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
                    circle.FadeOut(fadeOutDuration);

                break;

            case DrawableSlider slider:
                using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
                    slider.Body.FadeOut(longFadeDuration, Easing.Out);

                break;

            case DrawableSliderTick sliderTick:
                // slider ticks fade out over up to one second
                var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000);

                using (sliderTick.BeginAbsoluteSequence(sliderTick.HitObject.StartTime - tickFadeOutDuration, true))
                    sliderTick.FadeOut(tickFadeOutDuration);

                break;

            case DrawableSpinner spinner:
                // hide elements we don't care about.
                spinner.Disc.Hide();
                spinner.Ticks.Hide();
                spinner.Background.Hide();

                using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true))
                    spinner.FadeOut(fadeOutDuration);

                break;
            }
        }
Example #9
0
        private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state)
        {
            var     osuObject = (OsuHitObject)drawable.HitObject;
            Vector2 origin    = drawable.Position;

            Random objRand = new Random((int)osuObject.StartTime);

            // Wiggle all objects during TimePreempt
            int amountWiggles = (int)osuObject.TimePreempt / wiggle_duration;

            void wiggle()
            {
                float nextAngle = (float)(objRand.NextDouble() * 2 * Math.PI);
                float nextDist  = (float)(objRand.NextDouble() * wiggle_strength);

                drawable.MoveTo(new Vector2((float)(nextDist * Math.Cos(nextAngle) + origin.X), (float)(nextDist * Math.Sin(nextAngle) + origin.Y)), wiggle_duration);
            }

            for (int i = 0; i < amountWiggles; i++)
            {
                using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration, true))
                    wiggle();
            }

            // Keep wiggling sliders and spinners for their duration
            if (!(osuObject is IHasEndTime endTime))
            {
                return;
            }

            amountWiggles = (int)(endTime.Duration / wiggle_duration);

            for (int i = 0; i < amountWiggles; i++)
            {
                using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration, true))
                    wiggle();
            }
        }
            private void updateState(DrawableHitObject hitObject, ArmedState state)
            {
                if (state == ArmedState.Idle || hitAnimations.Value)
                {
                    return;
                }

                if (hitObject is DrawableHitCircle circle)
                {
                    circle.ApproachCircle
                    .FadeOutFromOne(editor_hit_object_fade_out_extension * 4)
                    .Expire();

                    circle.ApproachCircle.ScaleTo(1.1f, 300, Easing.OutQuint);
                }

                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
                    var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));

                    if (existing == null)
                    {
                        return;
                    }

                    hitObject.RemoveTransform(existing);

                    using (hitObject.BeginAbsoluteSequence(hitObject.HitStateUpdateTime))
                        hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
                    break;
                }
            }
Example #11
0
        protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state)
        {
            if (!(drawable is DrawableOsuHitObject d))
            {
                return;
            }

            var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.HitObject.TimeFadein;
            var fadeOutDuration  = d.HitObject.TimePreempt * fade_out_duration_multiplier;

            // new duration from completed fade in to end (before fading out)
            var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime;

            switch (drawable)
            {
            case DrawableHitCircle circle:
                // we don't want to see the approach circle
                circle.ApproachCircle.Hide();

                // fade out immediately after fade in.
                using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
                {
                    circle.FadeOut(fadeOutDuration);
                }

                break;

            case DrawableSlider slider:
                using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
                {
                    slider.Body.FadeOut(longFadeDuration, Easing.Out);
                }

                break;

            case DrawableSpinner spinner:
                // hide elements we don't care about.
                spinner.Disc.Hide();
                spinner.Ticks.Hide();
                spinner.Background.Hide();

                using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true))
                {
                    spinner.FadeOut(fadeOutDuration);
                }

                break;
            }
        }
Example #12
0
            private void updateState(DrawableHitObject hitObject, ArmedState state)
            {
                if (state == ArmedState.Idle || hitAnimations.Value)
                {
                    return;
                }

                // adjust the visuals of certain object types to make them stay on screen for longer than usual.
                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
                    .FadeOutFromOne(editor_hit_object_fade_out_extension * 4)
                    .Expire();

                    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;
                }

                // Get the existing fade out transform
                var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));

                if (existing == null)
                {
                    return;
                }

                hitObject.RemoveTransform(existing);

                using (hitObject.BeginAbsoluteSequence(hitObject.HitStateUpdateTime))
                    hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
            }
Example #13
0
        private void updateState(DrawableHitObject hitObject, ArmedState state)
        {
            switch (state)
            {
            case ArmedState.Miss:
                // Get the existing fade out transform
                var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));
                if (existing == null)
                {
                    return;
                }

                using (hitObject.BeginAbsoluteSequence(existing.StartTime))
                    hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
                break;
            }
        }
        private void updateState(DrawableHitObject hitObject, ArmedState state)
        {
            if (state == ArmedState.Idle)
            {
                return;
            }

            // adjust the visuals of certain object types to make them stay on screen for longer than usual.
            switch (hitObject)
            {
            default:
                // there are quite a few drawable hit types we don't want to extent (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
                .FadeOutFromOne(editor_hit_object_fade_out_extension)
                .Expire();
                break;
            }

            // Get the existing fade out transform
            var existing = hitObject.Transforms.LastOrDefault(t => t.TargetMember == nameof(Alpha));

            if (existing == null)
            {
                return;
            }

            hitObject.RemoveTransform(existing);

            using (hitObject.BeginAbsoluteSequence(existing.StartTime))
                hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire();
        }
Example #15
0
        protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
        {
            switch (hitObject)
            {
            case DrawableDrumRollTick _:
            case DrawableHit _:
                double preempt  = drawableRuleset.TimeRange.Value / drawableRuleset.ControlPointAt(hitObject.HitObject.StartTime).Multiplier;
                double start    = hitObject.HitObject.StartTime - preempt * fade_out_start_time;
                double duration = preempt * fade_out_duration;

                using (hitObject.BeginAbsoluteSequence(start))
                {
                    hitObject.FadeOut(duration);

                    // DrawableHitObject sets LifetimeEnd to LatestTransformEndTime if it isn't manually changed.
                    // in order for the object to not be killed before its actual end time (as the latest transform ends earlier), set lifetime end explicitly.
                    hitObject.LifetimeEnd = state == ArmedState.Idle || !hitObject.AllJudged
                            ? hitObject.HitObject.GetEndTime() + hitObject.HitObject.HitWindows.WindowFor(HitResult.Miss)
                            : hitObject.HitStateUpdateTime;
                }

                break;
            }
        }
Example #16
0
        private void applyState(DrawableHitObject drawable, bool increaseVisibility)
        {
            if (!(drawable is DrawableOsuHitObject d))
            {
                return;
            }

            var h = d.HitObject;

            var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadeIn;
            var fadeOutDuration  = h.TimePreempt * fade_out_duration_multiplier;

            // new duration from completed fade in to end (before fading out)
            var longFadeDuration = h.GetEndTime() - fadeOutStartTime;

            switch (drawable)
            {
            case DrawableSliderTail sliderTail:
                // use stored values from head circle to achieve same fade sequence.
                fadeOutDuration  = lastSliderHeadFadeOutDuration;
                fadeOutStartTime = lastSliderHeadFadeOutStartTime;

                using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
                    sliderTail.FadeOut(fadeOutDuration);

                break;

            case DrawableSliderRepeat sliderRepeat:
                // use stored values from head circle to achieve same fade sequence.
                fadeOutDuration  = lastSliderHeadFadeOutDuration;
                fadeOutStartTime = lastSliderHeadFadeOutStartTime;

                using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
                    // only apply to circle piece – reverse arrow is not affected by hidden.
                    sliderRepeat.CirclePiece.FadeOut(fadeOutDuration);

                break;

            case DrawableHitCircle circle:

                if (circle is DrawableSliderHead)
                {
                    lastSliderHeadFadeOutDuration  = fadeOutDuration;
                    lastSliderHeadFadeOutStartTime = fadeOutStartTime;
                }

                Drawable fadeTarget = circle;

                if (increaseVisibility)
                {
                    // only fade the circle piece (not the approach circle) for the increased visibility object.
                    fadeTarget = circle.CirclePiece;
                }
                else
                {
                    // we don't want to see the approach circle
                    using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true))
                        circle.ApproachCircle.Hide();
                }

                // fade out immediately after fade in.
                using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
                    fadeTarget.FadeOut(fadeOutDuration);
                break;

            case DrawableSlider slider:
                using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
                    slider.Body.FadeOut(longFadeDuration, Easing.Out);

                break;

            case DrawableSliderTick sliderTick:
                // slider ticks fade out over up to one second
                var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000);

                using (sliderTick.BeginAbsoluteSequence(sliderTick.HitObject.StartTime - tickFadeOutDuration, true))
                    sliderTick.FadeOut(tickFadeOutDuration);

                break;

            case DrawableSpinner spinner:
                // hide elements we don't care about.
                // todo: hide background

                using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true))
                    spinner.FadeOut(fadeOutDuration);

                break;
            }
        }