diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs new file mode 100644 index 0000000000..34e5e120f1 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCircleOverlapMarker.cs @@ -0,0 +1,87 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Utils; +using osu.Game.Graphics; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Skinning.Default; +using osu.Game.Screens.Edit; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components +{ + public class HitCircleOverlapMarker : BlueprintPiece + { + private readonly Circle circle; + private readonly RingPiece ring; + + [Resolved] + private EditorClock editorClock { get; set; } + + public HitCircleOverlapMarker() + { + Origin = Anchor.Centre; + + Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); + + InternalChildren = new Drawable[] + { + circle = new Circle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + ring = new RingPiece + { + BorderThickness = 4, + } + }; + } + + [Resolved] + private ISkinSource skin { get; set; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + circle.BorderColour = colours.Yellow; + } + + public override void UpdateFrom(HitCircle hitObject) + { + base.UpdateFrom(hitObject); + + Scale = new Vector2(hitObject.Scale); + + if ((hitObject is IHasComboInformation combo)) + ring.BorderColour = combo.GetComboColour(skin); + + bool hasReachedObject = editorClock.CurrentTime >= hitObject.StartTime; + float interpolation = Interpolation.ValueAt(editorClock.CurrentTime, 0, 1f, hitObject.StartTime, hitObject.StartTime + DrawableOsuEditorRuleset.EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION, Easing.In); + float interpolation2 = MathHelper.Clamp(Interpolation.ValueAt(editorClock.CurrentTime, 0, 1f, hitObject.StartTime, hitObject.StartTime + DrawableOsuEditorRuleset.EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION / 2, Easing.OutQuint), 0, 1); + float interpolation3 = Interpolation.ValueAt(editorClock.CurrentTime, 0, 1f, hitObject.StartTime, hitObject.StartTime + DrawableOsuEditorRuleset.EDITOR_HIT_OBJECT_FADE_OUT_EXTENSION); + + if (hasReachedObject) + { + circle.Scale = new Vector2(1 - 0.05f * interpolation3); + ring.Scale = new Vector2(1 + 0.1f * interpolation2); + Alpha = 0.9f * (1 - (interpolation)); + } + else + Alpha = 0; + } + + public override void Hide() + { + // intentional no op so we are not hidden when not selected. + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs index b21a3e038e..3f9cfe21d4 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCircleSelectionBlueprint.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; @@ -14,11 +15,16 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles protected new DrawableHitCircle DrawableObject => (DrawableHitCircle)base.DrawableObject; protected readonly HitCirclePiece CirclePiece; + private readonly HitCircleOverlapMarker marker; public HitCircleSelectionBlueprint(HitCircle circle) : base(circle) { - InternalChild = CirclePiece = new HitCirclePiece(); + InternalChildren = new Drawable[] + { + marker = new HitCircleOverlapMarker(), + CirclePiece = new HitCirclePiece(), + }; } protected override void Update() @@ -26,6 +32,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles base.Update(); CirclePiece.UpdateFrom(HitObject); + marker.UpdateFrom(HitObject); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.HitArea.ReceivePositionalInputAt(screenSpacePos); diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs index 241ff70a18..d31d2aed97 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleOverlay.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; @@ -13,20 +14,38 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private readonly Slider slider; private readonly SliderPosition position; + private readonly HitCircleOverlapMarker marker; public SliderCircleOverlay(Slider slider, SliderPosition position) { this.slider = slider; this.position = position; - InternalChild = CirclePiece = new HitCirclePiece(); + InternalChildren = new Drawable[] + { + marker = new HitCircleOverlapMarker(), + CirclePiece = new HitCirclePiece(), + }; } protected override void Update() { base.Update(); - CirclePiece.UpdateFrom(position == SliderPosition.Start ? (HitCircle)slider.HeadCircle : slider.TailCircle); + var circle = position == SliderPosition.Start ? (HitCircle)slider.HeadCircle : slider.TailCircle; + + CirclePiece.UpdateFrom(circle); + marker.UpdateFrom(circle); + } + + public override void Hide() + { + CirclePiece.Hide(); + } + + public override void Show() + { + CirclePiece.Show(); } } }