From c6c91cd9a5ce76554b277b0e7520e0aeb4312cef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Apr 2021 18:05:26 +0900 Subject: [PATCH 01/10] Refactor `WaveformOpacityMenuItem` to not receive whole config --- osu.Game/Screens/Edit/Editor.cs | 2 +- .../{WaveformOpacityMenu.cs => WaveformOpacityMenuItem.cs} | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) rename osu.Game/Screens/Edit/{WaveformOpacityMenu.cs => WaveformOpacityMenuItem.cs} (85%) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index fffea65456..360fbb36db 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -226,7 +226,7 @@ namespace osu.Game.Screens.Edit { Items = new[] { - new WaveformOpacityMenu(config) + new WaveformOpacityMenuItem(config.GetBindable(OsuSetting.EditorWaveformOpacity)), } } } diff --git a/osu.Game/Screens/Edit/WaveformOpacityMenu.cs b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs similarity index 85% rename from osu.Game/Screens/Edit/WaveformOpacityMenu.cs rename to osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs index 5d209ae141..053c2fa4b0 100644 --- a/osu.Game/Screens/Edit/WaveformOpacityMenu.cs +++ b/osu.Game/Screens/Edit/WaveformOpacityMenuItem.cs @@ -4,18 +4,17 @@ using System.Collections.Generic; using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; -using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit { - internal class WaveformOpacityMenu : MenuItem + internal class WaveformOpacityMenuItem : MenuItem { private readonly Bindable waveformOpacity; private readonly Dictionary menuItemLookup = new Dictionary(); - public WaveformOpacityMenu(OsuConfigManager config) + public WaveformOpacityMenuItem(Bindable waveformOpacity) : base("Waveform opacity") { Items = new[] @@ -26,7 +25,7 @@ namespace osu.Game.Screens.Edit createMenuItem(1f), }; - waveformOpacity = config.GetBindable(OsuSetting.EditorWaveformOpacity); + this.waveformOpacity = waveformOpacity; waveformOpacity.BindValueChanged(opacity => { foreach (var kvp in menuItemLookup) From 9d8f0c854d1bce0763c1e7e4113321a8e0646944 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Apr 2021 18:05:40 +0900 Subject: [PATCH 02/10] Setup configuration item for editor hit animations --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Screens/Edit/Editor.cs | 3 ++- .../Screens/Edit/HitAnimationsMenuItem.cs | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Screens/Edit/HitAnimationsMenuItem.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index f9b1c9618b..09412b1f1b 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -143,6 +143,7 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.DiscordRichPresence, DiscordRichPresenceMode.Full); SetDefault(OsuSetting.EditorWaveformOpacity, 0.25f); + SetDefault(OsuSetting.EditorHitAnimations, false); } public OsuConfigManager(Storage storage) @@ -266,6 +267,7 @@ namespace osu.Game.Configuration GameplayDisableWinKey, SeasonalBackgroundMode, EditorWaveformOpacity, + EditorHitAnimations, DiscordRichPresence, AutomaticallyDownloadWhenSpectating, ShowOnlineExplicitContent, diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 360fbb36db..da0e9ebbaf 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -224,9 +224,10 @@ namespace osu.Game.Screens.Edit }, new MenuItem("View") { - Items = new[] + Items = new MenuItem[] { new WaveformOpacityMenuItem(config.GetBindable(OsuSetting.EditorWaveformOpacity)), + new HitAnimationsMenuItem(config.GetBindable(OsuSetting.EditorHitAnimations)) } } } diff --git a/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs b/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs new file mode 100644 index 0000000000..fb7ab39f7a --- /dev/null +++ b/osu.Game/Screens/Edit/HitAnimationsMenuItem.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using JetBrains.Annotations; +using osu.Framework.Bindables; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Edit +{ + internal class HitAnimationsMenuItem : ToggleMenuItem + { + [UsedImplicitly] + private readonly Bindable hitAnimations; + + public HitAnimationsMenuItem(Bindable hitAnimations) + : base("Hit animations") + { + State.BindTo(this.hitAnimations = hitAnimations); + } + } +} From 47a4a07024b6557d475b92f1356ee15c0828376c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Apr 2021 19:15:10 +0900 Subject: [PATCH 03/10] Split out animation triggering of `MainCirclePiece` to be interface driven --- .../Objects/Drawables/DrawableHitCircle.cs | 2 ++ .../Skinning/Default/IMainCirclePiece.cs | 17 +++++++++++++++++ .../Skinning/Default/MainCirclePiece.cs | 7 ++----- .../Skinning/Legacy/LegacyMainCirclePiece.cs | 8 +++----- 4 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Skinning/Default/IMainCirclePiece.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index df77ec2693..fb6c110b3c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -182,6 +182,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // todo: temporary / arbitrary, used for lifetime optimisation. this.Delay(800).FadeOut(); + (CirclePiece.Drawable as IMainCirclePiece)?.Animate(state); + switch (state) { case ArmedState.Idle: diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/IMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/IMainCirclePiece.cs new file mode 100644 index 0000000000..17a1e29094 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/Default/IMainCirclePiece.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Skinning.Default +{ + public interface IMainCirclePiece + { + /// + /// Begins animating this . + /// + /// The of the related . + void Animate(ArmedState state); + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs index 46aeadc59b..b46baa00ba 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Default/MainCirclePiece.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Default { - public class MainCirclePiece : CompositeDrawable + public class MainCirclePiece : CompositeDrawable, IMainCirclePiece { private readonly CirclePiece circle; private readonly RingPiece ring; @@ -67,12 +67,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Default }, true); indexInCurrentCombo.BindValueChanged(index => number.Text = (index.NewValue + 1).ToString(), true); - - drawableObject.ApplyCustomUpdateState += updateState; - updateState(drawableObject, drawableObject.State.Value); } - private void updateState(DrawableHitObject drawableObject, ArmedState state) + public void Animate(ArmedState state) { using (BeginAbsoluteSequence(drawableObject.StateUpdateTime)) glow.FadeOut(400); diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index 545e80a709..cf62165929 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics.Sprites; 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; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -19,7 +20,7 @@ using static osu.Game.Skinning.LegacySkinConfiguration; namespace osu.Game.Rulesets.Osu.Skinning.Legacy { - public class LegacyMainCirclePiece : CompositeDrawable + public class LegacyMainCirclePiece : CompositeDrawable, IMainCirclePiece { private readonly string priorityLookup; private readonly bool hasNumber; @@ -138,12 +139,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy accentColour.BindValueChanged(colour => hitCircleSprite.Colour = LegacyColourCompatibility.DisallowZeroAlpha(colour.NewValue), true); if (hasNumber) indexInCurrentCombo.BindValueChanged(index => hitCircleText.Text = (index.NewValue + 1).ToString(), true); - - drawableObject.ApplyCustomUpdateState += updateState; - updateState(drawableObject, drawableObject.State.Value); } - private void updateState(DrawableHitObject drawableObject, ArmedState state) + public void Animate(ArmedState state) { const double legacy_fade_duration = 240; From f2824a222a13f924df12f4479ccf3b8d68e5f6b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Apr 2021 19:41:15 +0900 Subject: [PATCH 04/10] Adjust existing fades to close match stable editor --- osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index 5fdb79cbbd..dfb71d1d22 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Edit case DrawableHitCircle circle: // also handles slider heads circle.ApproachCircle - .FadeOutFromOne(editor_hit_object_fade_out_extension) + .FadeOutFromOne(editor_hit_object_fade_out_extension * 4) .Expire(); break; } @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Osu.Edit hitObject.RemoveTransform(existing); - using (hitObject.BeginAbsoluteSequence(existing.StartTime)) + using (hitObject.BeginAbsoluteSequence(hitObject.HitStateUpdateTime)) hitObject.FadeOut(editor_hit_object_fade_out_extension).Expire(); } } From 0f70469d1c33f392def6ae1070f51cdad941643c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 21 Apr 2021 19:44:17 +0900 Subject: [PATCH 05/10] Only apply custom editor overrides if hit animations is disabled --- .../Edit/DrawableOsuEditRuleset.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs index dfb71d1d22..b8d0637e90 100644 --- a/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs +++ b/osu.Game.Rulesets.Osu/Edit/DrawableOsuEditRuleset.cs @@ -3,8 +3,11 @@ using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -27,8 +30,16 @@ namespace osu.Game.Rulesets.Osu.Edit private class OsuEditPlayfield : OsuPlayfield { + private Bindable hitAnimations; + protected override GameplayCursorContainer CreateCursor() => null; + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + hitAnimations = config.GetBindable(OsuSetting.EditorHitAnimations); + } + protected override void OnNewDrawableHitObject(DrawableHitObject d) { d.ApplyCustomUpdateState += updateState; @@ -42,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.Edit private void updateState(DrawableHitObject hitObject, ArmedState state) { - if (state == ArmedState.Idle) + if (state == ArmedState.Idle || hitAnimations.Value) return; // adjust the visuals of certain object types to make them stay on screen for longer than usual. @@ -60,6 +71,15 @@ namespace osu.Game.Rulesets.Osu.Edit 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; } From 1884c18a2cc3d169012f89da64a16d65c7cd267f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Apr 2021 18:12:03 +0900 Subject: [PATCH 06/10] Ignore movement operations which have no offset --- osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index b1afbe0d61..f70e063ba9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -519,7 +519,8 @@ namespace osu.Game.Screens.Edit.Compose.Components // Apply the start time at the newly snapped-to position double offset = result.Time.Value - movementBlueprints.First().HitObject.StartTime; - Beatmap.PerformOnSelection(obj => obj.StartTime += offset); + if (offset != 0) + Beatmap.PerformOnSelection(obj => obj.StartTime += offset); } return true; From a5364b224f083be5d55a31c95203f7a65069f3cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Apr 2021 18:47:04 +0900 Subject: [PATCH 07/10] Add simple key based time nudging support to editor --- .../Editing/TestSceneEditorSelection.cs | 22 ++++++++++ .../Input/Bindings/GlobalActionContainer.cs | 8 ++++ .../Timeline/TimelineBlueprintContainer.cs | 42 ++++++++++++++++++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs index 99f31b0c2a..c783ea1448 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorSelection.cs @@ -41,6 +41,28 @@ namespace osu.Game.Tests.Visual.Editing }); } + [Test] + public void TestNudgeSelection() + { + HitCircle[] addedObjects = null; + + AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects = new[] + { + new HitCircle { StartTime = 100 }, + new HitCircle { StartTime = 200, Position = new Vector2(50) }, + new HitCircle { StartTime = 300, Position = new Vector2(100) }, + new HitCircle { StartTime = 400, Position = new Vector2(150) }, + })); + + AddStep("select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(addedObjects)); + + AddStep("nudge forwards", () => InputManager.Key(Key.K)); + AddAssert("objects moved forwards in time", () => addedObjects[0].StartTime > 100); + + AddStep("nudge backwards", () => InputManager.Key(Key.J)); + AddAssert("objects reverted to original position", () => addedObjects[0].StartTime == 100); + } + [Test] public void TestBasicSelect() { diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index e414e12dd1..6717de5658 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -71,6 +71,8 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.F3 }, GlobalAction.EditorTimingMode), new KeyBinding(new[] { InputKey.F4 }, GlobalAction.EditorSetupMode), new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.A }, GlobalAction.EditorVerifyMode), + new KeyBinding(new[] { InputKey.J }, GlobalAction.EditorNudgeLeft), + new KeyBinding(new[] { InputKey.K }, GlobalAction.EditorNudgeRight), }; public IEnumerable InGameKeyBindings => new[] @@ -251,5 +253,11 @@ namespace osu.Game.Input.Bindings [Description("Verify mode")] EditorVerifyMode, + + [Description("Nudge selection left")] + EditorNudgeLeft, + + [Description("Nudge selection right")] + EditorNudgeRight } } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index 7a3781a981..3555bc2800 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -12,9 +12,11 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Framework.Utils; using osu.Game.Graphics; +using osu.Game.Input.Bindings; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; @@ -237,10 +239,48 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline } } - internal class TimelineSelectionHandler : SelectionHandler + internal class TimelineSelectionHandler : SelectionHandler, IKeyBindingHandler { // for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation public override bool HandleMovement(MoveSelectionEvent moveEvent) => true; + + public bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.EditorNudgeLeft: + nudgeSelection(-1); + return true; + + case GlobalAction.EditorNudgeRight: + nudgeSelection(1); + return true; + } + + return false; + } + + public void OnReleased(GlobalAction action) + { + } + + /// + /// Nudge the current selection by the specified multiple of beat divisor lengths, + /// based on the timing at the first object in the selection. + /// + /// The direction and count of beat divisor lengths to adjust. + private void nudgeSelection(int amount) + { + var selected = EditorBeatmap.SelectedHitObjects; + + if (selected.Count == 0) + return; + + var timingPoint = EditorBeatmap.ControlPointInfo.TimingPointAt(selected.First().StartTime); + double adjustment = timingPoint.BeatLength / EditorBeatmap.BeatDivisor * amount; + + EditorBeatmap.PerformOnSelection(h => h.StartTime += adjustment); + } } private class TimelineDragBox : DragBox From 30e6ea4291dd95fb87108263df1f677e151d32f4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 22 Apr 2021 18:59:57 +0900 Subject: [PATCH 08/10] Add failing test --- .../TestSceneHoldNoteInput.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 42ea12214f..668487f673 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -324,6 +324,33 @@ namespace osu.Game.Rulesets.Mania.Tests assertTailJudgement(HitResult.Ok); } + [Test] + public void TestZeroLength() + { + var beatmap = new Beatmap + { + HitObjects = + { + new HoldNote + { + StartTime = 1000, + Duration = 0, + Column = 0, + }, + }, + BeatmapInfo = { Ruleset = new ManiaRuleset().RulesetInfo }, + }; + + performTest(new List + { + new ManiaReplayFrame(beatmap.HitObjects[0].StartTime, ManiaAction.Key1), + new ManiaReplayFrame(beatmap.HitObjects[0].GetEndTime() + 1), + }, beatmap); + + AddAssert("hold note hit", () => judgementResults.Where(j => beatmap.HitObjects[0].NestedHitObjects.Contains(j.HitObject)) + .All(j => j.Type.IsHit())); + } + private void assertHeadJudgement(HitResult result) => AddAssert($"head judged as {result}", () => judgementResults.First(j => j.HitObject is Note).Type == result); From 4148d473e3d4c949b312abcbc915f2fd3e99e925 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 22 Apr 2021 19:51:33 +0900 Subject: [PATCH 09/10] Fix hold note crashing with 0 length --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 828ee7b03e..02829d87bd 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // As the note is being held, adjust the size of the sizing container. This has two effects: // 1. The contained masking container will mask the body and ticks. // 2. The head note will move along with the new "head position" in the container. - if (Head.IsHit && releaseTime == null) + if (Head.IsHit && releaseTime == null && DrawHeight > 0) { // How far past the hit target this hold note is. Always a positive value. float yOffset = Math.Max(0, Direction.Value == ScrollingDirection.Up ? -Y : Y); From b4f492ca4ce6e171bd3ff9cfd02d5a98140f0666 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 22 Apr 2021 23:06:46 +0900 Subject: [PATCH 10/10] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 7b97103851..140057f9cc 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b27e00f59d..532dea7ace 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -29,7 +29,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d07e16ea56..edebefa70e 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - +