// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Skinning.Default; namespace osu.Game.Rulesets.Osu.Mods { public class OsuModTraceable : ModWithVisibilityAdjustment, IRequiresApproachCircles { public override string Name => "Traceable"; public override string Acronym => "TC"; public override ModType Type => ModType.Fun; public override LocalisableString Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(IHidesApproachCircles), typeof(OsuModDepth) }; protected override bool IsFirstAdjustableObject(HitObject hitObject) => !(hitObject is Spinner || hitObject is SpinnerTick); protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) { } protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) => applyTraceableState(hitObject, state); private void applyTraceableState(DrawableHitObject drawable, ArmedState state) { if (!(drawable is DrawableOsuHitObject)) return; //todo: expose and hide spinner background somehow switch (drawable) { case DrawableHitCircle circle: // we only want to see the approach circle applyCirclePieceState(circle, circle.CirclePiece); break; case DrawableSliderTail sliderTail: applyCirclePieceState(sliderTail); break; case DrawableSliderRepeat sliderRepeat: // show only the repeat arrow applyCirclePieceState(sliderRepeat, sliderRepeat.CirclePiece); break; case DrawableSlider slider: slider.Body.OnSkinChanged += () => applySliderState(slider); applySliderState(slider); break; } } private void applyCirclePieceState(DrawableOsuHitObject hitObject, IDrawable? hitCircle = null) { var h = hitObject.HitObject; using (hitObject.BeginAbsoluteSequence(h.StartTime - h.TimePreempt)) (hitCircle ?? hitObject).Hide(); } private void applySliderState(DrawableSlider slider) { ((PlaySliderBody)slider.Body.Drawable).AccentColour = slider.AccentColour.Value.Opacity(0); ((PlaySliderBody)slider.Body.Drawable).BorderColour = slider.AccentColour.Value; } } }