Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lingering hitobject display to editor, replacing "Hit Animations" toggle #18239

Merged
merged 13 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 0 additions & 114 deletions osu.Game.Rulesets.Osu.Tests/Editor/TestSceneOsuEditorHitAnimations.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// 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.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Utils;
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<HitCircle>
{
/// <summary>
/// Hit objects are intentionally made to fade out at a constant slower rate than in gameplay.
/// This allows a mapper to gain better historical context and use recent hitobjects as reference / snap points.
/// </summary>
public const double FADE_OUT_EXTENSION = 700;

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[]
{
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; }

public override void UpdateFrom(HitCircle hitObject)
{
base.UpdateFrom(hitObject);

Scale = new Vector2(hitObject.Scale);

if (hitObject is IHasComboInformation combo)
ring.BorderColour = combo.GetComboColour(skin);

double editorTime = editorClock.CurrentTime;
double hitObjectTime = hitObject.StartTime;
bool hasReachedObject = editorTime >= hitObjectTime;

if (hasReachedObject)
{
float alpha = Interpolation.ValueAt(editorTime, 0, 1f, hitObjectTime, hitObjectTime + FADE_OUT_EXTENSION, Easing.In);
float ringScale = MathHelper.Clamp(Interpolation.ValueAt(editorTime, 0, 1f, hitObjectTime, hitObjectTime + FADE_OUT_EXTENSION / 2, Easing.OutQuint), 0, 1);

ring.Scale = new Vector2(1 + 0.1f * ringScale);
Alpha = 0.9f * (1 - alpha);
}
else
Alpha = 0;
}

public override void Hide()
{
// intentional no op so we are not hidden when not selected.
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
Expand All @@ -14,18 +15,24 @@ public class HitCircleSelectionBlueprint : OsuSelectionBlueprint<HitCircle>
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()
{
base.Update();

CirclePiece.UpdateFrom(HitObject);
marker.UpdateFrom(HitObject);
}

public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.HitArea.ReceivePositionalInputAt(screenSpacePos);
Expand Down
10 changes: 10 additions & 0 deletions osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
// 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.Framework.Allocation;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Screens.Edit;

namespace osu.Game.Rulesets.Osu.Edit.Blueprints
{
public abstract class OsuSelectionBlueprint<T> : HitObjectSelectionBlueprint<T>
where T : OsuHitObject
{
[Resolved]
private EditorClock editorClock { get; set; }
bdach marked this conversation as resolved.
Show resolved Hide resolved

protected new DrawableOsuHitObject DrawableObject => (DrawableOsuHitObject)base.DrawableObject;

protected override bool AlwaysShowWhenSelected => true;

protected override bool ShouldBeAlive => base.ShouldBeAlive
|| (editorClock.CurrentTime >= Item.StartTime && editorClock.CurrentTime - Item.GetEndTime() < HitCircleOverlapMarker.FADE_OUT_EXTENSION);

protected OsuSelectionBlueprint(T hitObject)
: base(hitObject)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
using osu.Game.Rulesets.Osu.Objects;
Expand All @@ -13,20 +14,38 @@ public class SliderCircleOverlay : CompositeDrawable

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();
}
}
}
Loading