From 0ef3bae26a4483fd12c21a34ff38d3fe6f69775d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 May 2020 18:34:51 +0900 Subject: [PATCH 01/27] Expose playfield from IManiaHitObjectComposer --- .../ManiaPlacementBlueprintTestScene.cs | 2 +- .../ManiaSelectionBlueprintTestScene.cs | 2 +- osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs | 2 -- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs index aac77c9c1c..39d5f50459 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs @@ -49,6 +49,6 @@ namespace osu.Game.Rulesets.Mania.Tests public Column ColumnAt(Vector2 screenSpacePosition) => column; - public int TotalColumns => 1; + public ManiaPlayfield Playfield => null; } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs index b598893e8c..d6dee92ba6 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs @@ -33,6 +33,6 @@ namespace osu.Game.Rulesets.Mania.Tests public Column ColumnAt(Vector2 screenSpacePosition) => column; - public int TotalColumns => 1; + public ManiaPlayfield Playfield => null; } } diff --git a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs index f64bab1fae..9b5d290fa8 100644 --- a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Mania.Edit { Column ColumnAt(Vector2 screenSpacePosition); - int TotalColumns { get; } + ManiaPlayfield Playfield { get; } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index dfa933baad..d7c0889c0d 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -42,8 +42,6 @@ namespace osu.Game.Rulesets.Mania.Edit public IScrollingInfo ScrollingInfo => drawableRuleset.ScrollingInfo; - public int TotalColumns => Playfield.TotalColumns; - public override (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) { var hoc = Playfield.GetColumn(0).HitObjectContainer; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 55245198c8..83049ff959 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Mania.Edit maxColumn = obj.Column; } - columnDelta = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + columnDelta = Math.Clamp(columnDelta, -minColumn, composer.Playfield.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; From 16585f767edb0f877cd04eba61ef662f7ecdca59 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 May 2020 19:17:24 +0900 Subject: [PATCH 02/27] Add initial beat snap grid implementation --- .../TestSceneManiaBeatSnapGrid.cs | 73 ++++++ .../Edit/ManiaBeatSnapGrid.cs | 233 ++++++++++++++++++ osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 + 3 files changed, 308 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs new file mode 100644 index 0000000000..84419313e6 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs @@ -0,0 +1,73 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Framework.Timing; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Configuration; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Edit; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Screens.Edit; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [Cached(typeof(IManiaHitObjectComposer))] + public class TestSceneManiaBeatSnapGrid : EditorClockTestScene, IManiaHitObjectComposer + { + [Cached(typeof(IScrollingInfo))] + private ScrollingTestContainer.TestScrollingInfo scrollingInfo = new ScrollingTestContainer.TestScrollingInfo(); + + [Cached(typeof(EditorBeatmap))] + private EditorBeatmap editorBeatmap = new EditorBeatmap(new ManiaBeatmap(new StageDefinition())); + + private readonly ManiaBeatSnapGrid beatSnapGrid; + + public TestSceneManiaBeatSnapGrid() + { + editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 200 }); + editorBeatmap.ControlPointInfo.Add(10000, new TimingControlPoint { BeatLength = 200 }); + + BeatDivisor.Value = 3; + + // Some sane defaults + scrollingInfo.Algorithm.Algorithm = ScrollVisualisationMethod.Constant; + scrollingInfo.Direction.Value = ScrollingDirection.Up; + scrollingInfo.TimeRange.Value = 1000; + + Children = new Drawable[] + { + Playfield = new ManiaPlayfield(new List + { + new StageDefinition { Columns = 4 }, + new StageDefinition { Columns = 3 } + }) + { + Clock = new FramedClock(new StopwatchClock()) + }, + beatSnapGrid = new ManiaBeatSnapGrid() + }; + } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + // We're providing a constant scroll algorithm. + float relativePosition = Playfield.Stages[0].HitObjectContainer.ToLocalSpace(e.ScreenSpaceMousePosition).Y / Playfield.Stages[0].HitObjectContainer.DrawHeight; + double timeValue = scrollingInfo.TimeRange.Value * relativePosition; + + beatSnapGrid.SetRange(timeValue, timeValue); + + return true; + } + + public Column ColumnAt(Vector2 screenSpacePosition) => null; + + public ManiaPlayfield Playfield { get; } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs new file mode 100644 index 0000000000..5a3fe29770 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -0,0 +1,233 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Screens.Edit; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaBeatSnapGrid : CompositeDrawable + { + [Resolved] + private IManiaHitObjectComposer composer { get; set; } + + [Resolved] + private EditorBeatmap beatmap { get; set; } + + [Resolved] + private IScrollingInfo scrollingInfo { get; set; } + + [Resolved] + private Bindable working { get; set; } + + [Resolved] + private OsuColour colours { get; set; } + + [Resolved] + private BindableBeatDivisor beatDivisor { get; set; } + + private readonly List grids = new List(); + + [BackgroundDependencyLoader] + private void load() + { + foreach (var stage in composer.Playfield.Stages) + { + var grid = new Grid(stage); + grids.Add(grid); + + AddInternal(grid); + } + + beatDivisor.BindValueChanged(_ => createLines(), true); + } + + private void createLines() + { + foreach (var grid in grids) + grid.Clear(); + + for (int i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) + { + var point = beatmap.ControlPointInfo.TimingPoints[i]; + var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; + + int beat = 0; + + for (double t = point.Time; t < until; t += point.BeatLength / beatDivisor.Value) + { + var indexInBeat = beat % beatDivisor.Value; + Color4 colour; + + if (indexInBeat == 0) + colour = BindableBeatDivisor.GetColourFor(1, colours); + else + { + var divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value); + colour = BindableBeatDivisor.GetColourFor(divisor, colours); + } + + foreach (var grid in grids) + grid.Add(new DrawableGridLine(t, colour)); + + beat++; + } + } + } + + public (Vector2 position, double time)? GetSnappedPosition(Vector2 position) + { + float minDist = float.PositiveInfinity; + DrawableGridLine minDistLine = null; + Vector2 minDistLinePosition = Vector2.Zero; + + foreach (var grid in grids) + { + foreach (var line in grid.AliveObjects.OfType()) + { + Vector2 linePos = line.ToSpaceOfOtherDrawable(line.OriginPosition, this); + float d = Vector2.Distance(position, linePos); + + if (d < minDist) + { + minDist = d; + minDistLine = line; + minDistLinePosition = linePos; + } + } + } + + if (minDistLine == null) + return null; + + float noteOffset = (scrollingInfo.Direction.Value == ScrollingDirection.Up ? 1 : -1) * DefaultNotePiece.NOTE_HEIGHT / 2; + return (new Vector2(position.X, minDistLinePosition.Y + noteOffset), minDistLine.HitObject.StartTime); + } + + public void SetRange(double minTime, double maxTime) => Schedule(() => + { + var linesBefore = new List(); + var linesDuring = new List(); + var linesAfter = new List(); + + foreach (var grid in grids) + { + linesBefore.Clear(); + linesDuring.Clear(); + linesAfter.Clear(); + + foreach (var line in grid.Objects.OfType()) + { + if (line.HitObject.StartTime < minTime) + linesBefore.Add(line); + else if (line.HitObject.StartTime <= maxTime) + linesDuring.Add(line); + else + linesAfter.Add(line); + } + + foreach (var l in linesDuring) + l.Colour = OsuColour.Gray(0.5f); + + for (int i = 0; i < linesBefore.Count; i++) + { + int offset = (linesBefore.Count - i - 1) / beatDivisor.Value; + linesBefore[i].Colour = OsuColour.Gray(0.5f / (offset + 1)); + } + + for (int i = 0; i < linesAfter.Count; i++) + { + int offset = i / beatDivisor.Value; + linesAfter[i].Colour = OsuColour.Gray(0.5f / (offset + 1)); + } + } + }); + + private class Grid : ScrollingHitObjectContainer + { + [Resolved] + private IManiaHitObjectComposer composer { get; set; } + + private readonly Stage stage; + + public Grid(Stage stage) + { + this.stage = stage; + + RelativeSizeAxes = Axes.None; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Clock = composer.Playfield.Clock; + } + + protected override void Update() + { + base.Update(); + + var parentQuad = Parent.ToLocalSpace(stage.HitObjectContainer.ScreenSpaceDrawQuad); + Position = parentQuad.TopLeft; + Size = parentQuad.Size; + } + } + + private class DrawableGridLine : DrawableHitObject + { + [Resolved] + private IScrollingInfo scrollingInfo { get; set; } + + private readonly IBindable direction = new Bindable(); + + public DrawableGridLine(double startTime, Color4 colour) + : base(new HitObject { StartTime = startTime }) + { + RelativeSizeAxes = Axes.X; + Height = 2; + + AddInternal(new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colour + }); + } + + [BackgroundDependencyLoader] + private void load() + { + direction.BindTo(scrollingInfo.Direction); + direction.BindValueChanged(onDirectionChanged, true); + } + + private void onDirectionChanged(ValueChangedEvent direction) + { + Origin = Anchor = direction.NewValue == ScrollingDirection.Up + ? Anchor.TopLeft + : Anchor.BottomLeft; + } + + protected override void UpdateStateTransforms(ArmedState state) + { + using (BeginAbsoluteSequence(HitObject.StartTime + 1000)) + this.FadeOut(); + } + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 1af7d06998..271e432e8d 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.UI [Cached] public class ManiaPlayfield : ScrollingPlayfield { + public IReadOnlyList Stages => stages; + private readonly List stages = new List(); public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos)); From 91d1b15d5ad141444259933678490df5db29794c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 May 2020 19:55:07 +0900 Subject: [PATCH 03/27] Integrate grid with the mania composer --- .../Edit/ManiaHitObjectComposer.cs | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index d7c0889c0d..11523dd384 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -6,9 +6,12 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Mania.Objects; using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Input; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; @@ -20,12 +23,27 @@ namespace osu.Game.Rulesets.Mania.Edit public class ManiaHitObjectComposer : HitObjectComposer, IManiaHitObjectComposer { private DrawableManiaEditRuleset drawableRuleset; + private ManiaBeatSnapGrid beatSnapGrid; + private InputManager inputManager; public ManiaHitObjectComposer(Ruleset ruleset) : base(ruleset) { } + [BackgroundDependencyLoader] + private void load() + { + AddInternal(beatSnapGrid = new ManiaBeatSnapGrid()); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + inputManager = GetContainingInputManager(); + } + /// /// Retrieves the column that intersects a screen-space position. /// @@ -42,11 +60,43 @@ namespace osu.Game.Rulesets.Mania.Edit public IScrollingInfo ScrollingInfo => drawableRuleset.ScrollingInfo; + protected override void Update() + { + base.Update(); + + if (BlueprintContainer.CurrentTool is SelectTool) + { + if (EditorBeatmap.SelectedHitObjects.Any()) + { + beatSnapGrid.SetRange(EditorBeatmap.SelectedHitObjects.Min(h => h.StartTime), EditorBeatmap.SelectedHitObjects.Max(h => h.GetEndTime())); + beatSnapGrid.Show(); + } + else + beatSnapGrid.Hide(); + } + else + { + var placementTime = GetSnappedPosition(ToLocalSpace(inputManager.CurrentState.Mouse.Position), 0).time; + beatSnapGrid.SetRange(placementTime, placementTime); + + beatSnapGrid.Show(); + } + } + public override (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) { - var hoc = Playfield.GetColumn(0).HitObjectContainer; + var beatSnapped = beatSnapGrid.GetSnappedPosition(position); - float targetPosition = hoc.ToLocalSpace(ToScreenSpace(position)).Y; + if (beatSnapped != null) + return beatSnapped.Value; + + return base.GetSnappedPosition(position, getTimeFromPosition(ToScreenSpace(position))); + } + + private double getTimeFromPosition(Vector2 screenSpacePosition) + { + var hoc = Playfield.Stages[0].HitObjectContainer; + float targetPosition = hoc.ToLocalSpace(screenSpacePosition).Y; if (drawableRuleset.ScrollingInfo.Direction.Value == ScrollingDirection.Down) { @@ -56,12 +106,10 @@ namespace osu.Game.Rulesets.Mania.Edit targetPosition = hoc.DrawHeight - targetPosition; } - double targetTime = drawableRuleset.ScrollingInfo.Algorithm.TimeAt(targetPosition, + return drawableRuleset.ScrollingInfo.Algorithm.TimeAt(targetPosition, EditorClock.CurrentTime, drawableRuleset.ScrollingInfo.TimeRange.Value, hoc.DrawHeight); - - return base.GetSnappedPosition(position, targetTime); } protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) From 42c3d892cd93a3671de896af87136244b36856c2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 May 2020 19:55:14 +0900 Subject: [PATCH 04/27] Only update alive lines --- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 5a3fe29770..320912ed5b 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Mania.Edit linesDuring.Clear(); linesAfter.Clear(); - foreach (var line in grid.Objects.OfType()) + foreach (var line in grid.AliveObjects.OfType()) { if (line.HitObject.StartTime < minTime) linesBefore.Add(line); From 0e334940745c5958a30a877083907ca391282953 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 May 2020 19:58:39 +0900 Subject: [PATCH 05/27] Fix flashing when changing beat divisor --- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 12 ++++++++++-- .../Edit/ManiaHitObjectComposer.cs | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 320912ed5b..9cb9256a7e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -119,7 +119,15 @@ namespace osu.Game.Rulesets.Mania.Edit return (new Vector2(position.X, minDistLinePosition.Y + noteOffset), minDistLine.HitObject.StartTime); } - public void SetRange(double minTime, double maxTime) => Schedule(() => + public void SetRange(double minTime, double maxTime) + { + if (LoadState >= LoadState.Ready) + setRange(minTime, maxTime); + else + Schedule(() => setRange(minTime, maxTime)); + } + + private void setRange(double minTime, double maxTime) { var linesBefore = new List(); var linesDuring = new List(); @@ -156,7 +164,7 @@ namespace osu.Game.Rulesets.Mania.Edit linesAfter[i].Colour = OsuColour.Gray(0.5f / (offset + 1)); } } - }); + } private class Grid : ScrollingHitObjectContainer { diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 11523dd384..1266761d12 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -60,9 +60,9 @@ namespace osu.Game.Rulesets.Mania.Edit public IScrollingInfo ScrollingInfo => drawableRuleset.ScrollingInfo; - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); if (BlueprintContainer.CurrentTool is SelectTool) { From 3441ab457d7d05dffa990117aa7ab3b84ceaa709 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 14 May 2020 20:06:34 +0900 Subject: [PATCH 06/27] Fix hitobjects placed at non-beatsnapped times --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 3fb03d642f..5fe53557b3 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -24,10 +24,15 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected Column Column; /// - /// The current mouse position, snapped to the closest column. + /// The current beat-snapped mouse position, snapped to the closest column. /// protected Vector2 SnappedMousePosition { get; private set; } + /// + /// The gameplay time at the current beat-snapped mouse position (). + /// + protected double SnappedTime { get; private set; } + /// /// The width of the closest column to the current mouse position. /// @@ -39,6 +44,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } + [Resolved] + private IDistanceSnapProvider snapProvider { get; set; } + protected ManiaPlacementBlueprint(T hitObject) : base(hitObject) { @@ -54,7 +62,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints return base.OnMouseDown(e); HitObject.Column = Column.Index; - BeginPlacement(TimeAt(e.ScreenSpaceMousePosition), true); + BeginPlacement(SnappedTime, true); return true; } @@ -70,6 +78,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints // Snap to the column var parentPos = Parent.ToLocalSpace(Column.ToScreenSpace(new Vector2(Column.DrawWidth / 2, 0))); SnappedMousePosition = new Vector2(parentPos.X, Parent.ToLocalSpace(screenSpacePosition).Y); + + SnappedTime = TimeAt(screenSpacePosition); + if (snapProvider != null) + (SnappedMousePosition, SnappedTime) = snapProvider.GetSnappedPosition(SnappedMousePosition, SnappedTime); } protected double TimeAt(Vector2 screenSpacePosition) From 4cbd51feb965fe78ba3429728205715788a83558 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 May 2020 13:08:15 +0900 Subject: [PATCH 07/27] Fix test errors --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 5fe53557b3..184356b89c 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } - [Resolved] + [Resolved(CanBeNull = true)] private IDistanceSnapProvider snapProvider { get; set; } protected ManiaPlacementBlueprint(T hitObject) From 392d44e1fbe8fcf6f334fe31134821a01e7adbf5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 May 2020 15:49:50 +0900 Subject: [PATCH 08/27] Always fully display one beat --- .../Edit/ManiaBeatSnapGrid.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 9cb9256a7e..63e887714b 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.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 System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -149,6 +150,29 @@ namespace osu.Game.Rulesets.Mania.Edit linesAfter.Add(line); } + // Snapping will always happen on one of the two lines around minTime (the "target" line). + // One of those lines may exist in linesBefore and the other may exist in linesAfter, depending on whether such a line exists, and the target changes when the mid-point is crossed. + // For display purposes, one complete beat is shown at the maximum brightness such that the target line should always be bright. + bool targetLineIsLastLineBefore = false; + + if (linesBefore.Count > 0 && linesAfter.Count > 0) + targetLineIsLastLineBefore = Math.Abs(linesBefore[^1].HitObject.StartTime - minTime) <= Math.Abs(linesAfter[0].HitObject.StartTime - minTime); + else if (linesBefore.Count > 0) + targetLineIsLastLineBefore = true; + + if (targetLineIsLastLineBefore) + { + // Move the last line before to linesDuring + linesDuring.Insert(0, linesBefore[^1]); + linesBefore.RemoveAt(linesBefore.Count - 1); + } + else if (linesAfter.Count > 0) // = false does not guarantee that a line after exists (maybe at the bottom of the screen) + { + // Move the first line after to linesDuring + linesDuring.Insert(0, linesAfter[0]); + linesAfter.RemoveAt(0); + } + foreach (var l in linesDuring) l.Colour = OsuColour.Gray(0.5f); From 1c6c128d1100ca3aa8ddd151c2f46a08701c30ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 May 2020 15:51:54 +0900 Subject: [PATCH 09/27] Add const --- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 63e887714b..77d42a0927 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -24,6 +24,11 @@ namespace osu.Game.Rulesets.Mania.Edit { public class ManiaBeatSnapGrid : CompositeDrawable { + /// + /// The brightness of bar lines one beat around the time range from . + /// + private const float first_beat_brightness = 0.5f; + [Resolved] private IManiaHitObjectComposer composer { get; set; } @@ -174,18 +179,18 @@ namespace osu.Game.Rulesets.Mania.Edit } foreach (var l in linesDuring) - l.Colour = OsuColour.Gray(0.5f); + l.Colour = OsuColour.Gray(first_beat_brightness); for (int i = 0; i < linesBefore.Count; i++) { int offset = (linesBefore.Count - i - 1) / beatDivisor.Value; - linesBefore[i].Colour = OsuColour.Gray(0.5f / (offset + 1)); + linesBefore[i].Colour = OsuColour.Gray(first_beat_brightness / (offset + 1)); } for (int i = 0; i < linesAfter.Count; i++) { int offset = i / beatDivisor.Value; - linesAfter[i].Colour = OsuColour.Gray(0.5f / (offset + 1)); + linesAfter[i].Colour = OsuColour.Gray(first_beat_brightness / (offset + 1)); } } } From 238d87f97611be6b137e8bcc9c30073e318518a8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 15 May 2020 15:56:32 +0900 Subject: [PATCH 10/27] Add comment about gray usage --- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 77d42a0927..31ebb7bc1c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -178,6 +178,8 @@ namespace osu.Game.Rulesets.Mania.Edit linesAfter.RemoveAt(0); } + // Grays are used rather than transparency since the lines appear on a coloured mania playfield. + foreach (var l in linesDuring) l.Colour = OsuColour.Gray(first_beat_brightness); From d9bb90078b5f0b9d4c32635417f818fe1c562073 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 May 2020 17:47:47 +0900 Subject: [PATCH 11/27] Move grids to inside columns --- .../Edit/ManiaBeatSnapGrid.cs | 48 +++++++++---------- osu.Game.Rulesets.Mania/UI/Column.cs | 2 + .../UI/Components/ColumnHitObjectArea.cs | 8 ++++ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 31ebb7bc1c..9a998366e9 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -7,12 +7,10 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; @@ -22,7 +20,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaBeatSnapGrid : CompositeDrawable + public class ManiaBeatSnapGrid : Component { /// /// The brightness of bar lines one beat around the time range from . @@ -54,15 +52,32 @@ namespace osu.Game.Rulesets.Mania.Edit { foreach (var stage in composer.Playfield.Stages) { - var grid = new Grid(stage); - grids.Add(grid); + foreach (var column in stage.Columns) + { + var grid = new Grid(); - AddInternal(grid); + grids.Add(grid); + column.UnderlayElements.Add(grid); + } } beatDivisor.BindValueChanged(_ => createLines(), true); } + public override void Hide() + { + base.Hide(); + foreach (var grid in grids) + grid.Hide(); + } + + public override void Show() + { + base.Show(); + foreach (var grid in grids) + grid.Show(); + } + private void createLines() { foreach (var grid in grids) @@ -145,7 +160,7 @@ namespace osu.Game.Rulesets.Mania.Edit linesDuring.Clear(); linesAfter.Clear(); - foreach (var line in grid.AliveObjects.OfType()) + foreach (var line in grid.Objects.OfType()) { if (line.HitObject.StartTime < minTime) linesBefore.Add(line); @@ -202,30 +217,11 @@ namespace osu.Game.Rulesets.Mania.Edit [Resolved] private IManiaHitObjectComposer composer { get; set; } - private readonly Stage stage; - - public Grid(Stage stage) - { - this.stage = stage; - - RelativeSizeAxes = Axes.None; - } - protected override void LoadComplete() { base.LoadComplete(); - Clock = composer.Playfield.Clock; } - - protected override void Update() - { - base.Update(); - - var parentQuad = Parent.ToLocalSpace(stage.HitObjectContainer.ScreenSpaceDrawQuad); - Position = parentQuad.TopLeft; - Size = parentQuad.Size; - } } private class DrawableGridLine : DrawableHitObject diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 506a07f26b..511d6c8623 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -37,6 +37,8 @@ namespace osu.Game.Rulesets.Mania.UI internal readonly Container TopLevelContainer; + public Container UnderlayElements => hitObjectArea.UnderlayElements; + public Column(int index) { Index = index; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index cb79bf7f43..b365ae45a9 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -12,6 +12,9 @@ namespace osu.Game.Rulesets.Mania.UI.Components public class ColumnHitObjectArea : HitObjectArea { public readonly Container Explosions; + + public readonly Container UnderlayElements; + private readonly Drawable hitTarget; public ColumnHitObjectArea(int columnIndex, HitObjectContainer hitObjectContainer) @@ -19,6 +22,11 @@ namespace osu.Game.Rulesets.Mania.UI.Components { AddRangeInternal(new[] { + UnderlayElements = new Container + { + RelativeSizeAxes = Axes.Both, + Depth = 2, + }, hitTarget = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HitTarget, columnIndex), _ => new DefaultHitTarget()) { RelativeSizeAxes = Axes.X, From 16e85ae0b1c0399b2a3dce77df4758b3c51f6079 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 May 2020 17:52:04 +0900 Subject: [PATCH 12/27] Remove Grid class --- .../Edit/ManiaBeatSnapGrid.cs | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 9a998366e9..5b13b1421c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.Edit [Resolved] private BindableBeatDivisor beatDivisor { get; set; } - private readonly List grids = new List(); + private readonly List grids = new List(); [BackgroundDependencyLoader] private void load() @@ -54,10 +54,10 @@ namespace osu.Game.Rulesets.Mania.Edit { foreach (var column in stage.Columns) { - var grid = new Grid(); + var lineContainer = new ScrollingHitObjectContainer(); - grids.Add(grid); - column.UnderlayElements.Add(grid); + grids.Add(lineContainer); + column.UnderlayElements.Add(lineContainer); } } @@ -212,18 +212,6 @@ namespace osu.Game.Rulesets.Mania.Edit } } - private class Grid : ScrollingHitObjectContainer - { - [Resolved] - private IManiaHitObjectComposer composer { get; set; } - - protected override void LoadComplete() - { - base.LoadComplete(); - Clock = composer.Playfield.Clock; - } - } - private class DrawableGridLine : DrawableHitObject { [Resolved] From b35b150f3883609e62e31e8bb6216e82b888cc6c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 May 2020 19:32:14 +0900 Subject: [PATCH 13/27] Simplify colouring logic --- .../Edit/ManiaBeatSnapGrid.cs | 66 +++---------------- 1 file changed, 9 insertions(+), 57 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 5b13b1421c..e771a9753f 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -22,10 +22,7 @@ namespace osu.Game.Rulesets.Mania.Edit { public class ManiaBeatSnapGrid : Component { - /// - /// The brightness of bar lines one beat around the time range from . - /// - private const float first_beat_brightness = 0.5f; + private const double visible_range = 1500; [Resolved] private IManiaHitObjectComposer composer { get; set; } @@ -150,64 +147,19 @@ namespace osu.Game.Rulesets.Mania.Edit private void setRange(double minTime, double maxTime) { - var linesBefore = new List(); - var linesDuring = new List(); - var linesAfter = new List(); - foreach (var grid in grids) { - linesBefore.Clear(); - linesDuring.Clear(); - linesAfter.Clear(); - foreach (var line in grid.Objects.OfType()) { - if (line.HitObject.StartTime < minTime) - linesBefore.Add(line); - else if (line.HitObject.StartTime <= maxTime) - linesDuring.Add(line); + double lineTime = line.HitObject.StartTime; + + if (lineTime >= minTime && lineTime <= maxTime) + line.Colour = Color4.White; else - linesAfter.Add(line); - } - - // Snapping will always happen on one of the two lines around minTime (the "target" line). - // One of those lines may exist in linesBefore and the other may exist in linesAfter, depending on whether such a line exists, and the target changes when the mid-point is crossed. - // For display purposes, one complete beat is shown at the maximum brightness such that the target line should always be bright. - bool targetLineIsLastLineBefore = false; - - if (linesBefore.Count > 0 && linesAfter.Count > 0) - targetLineIsLastLineBefore = Math.Abs(linesBefore[^1].HitObject.StartTime - minTime) <= Math.Abs(linesAfter[0].HitObject.StartTime - minTime); - else if (linesBefore.Count > 0) - targetLineIsLastLineBefore = true; - - if (targetLineIsLastLineBefore) - { - // Move the last line before to linesDuring - linesDuring.Insert(0, linesBefore[^1]); - linesBefore.RemoveAt(linesBefore.Count - 1); - } - else if (linesAfter.Count > 0) // = false does not guarantee that a line after exists (maybe at the bottom of the screen) - { - // Move the first line after to linesDuring - linesDuring.Insert(0, linesAfter[0]); - linesAfter.RemoveAt(0); - } - - // Grays are used rather than transparency since the lines appear on a coloured mania playfield. - - foreach (var l in linesDuring) - l.Colour = OsuColour.Gray(first_beat_brightness); - - for (int i = 0; i < linesBefore.Count; i++) - { - int offset = (linesBefore.Count - i - 1) / beatDivisor.Value; - linesBefore[i].Colour = OsuColour.Gray(first_beat_brightness / (offset + 1)); - } - - for (int i = 0; i < linesAfter.Count; i++) - { - int offset = i / beatDivisor.Value; - linesAfter[i].Colour = OsuColour.Gray(first_beat_brightness / (offset + 1)); + { + double timeSeparation = lineTime < minTime ? minTime - lineTime : lineTime - maxTime; + line.Colour = OsuColour.Gray((float)Math.Max(0, 1 - timeSeparation / visible_range)); + } } } } From 406f39e8bfc281fc91c3e96ce12077423974006f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 18 May 2020 21:27:26 +0900 Subject: [PATCH 14/27] Construct online visible lines --- .../TestSceneManiaBeatSnapGrid.cs | 2 +- .../Edit/ManiaBeatSnapGrid.cs | 135 ++++++++++-------- .../Edit/ManiaHitObjectComposer.cs | 9 +- 3 files changed, 81 insertions(+), 65 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs index 84419313e6..941cf4e7c8 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Tests float relativePosition = Playfield.Stages[0].HitObjectContainer.ToLocalSpace(e.ScreenSpaceMousePosition).Y / Playfield.Stages[0].HitObjectContainer.DrawHeight; double timeValue = scrollingInfo.TimeRange.Value * relativePosition; - beatSnapGrid.SetRange(timeValue, timeValue); + beatSnapGrid.SelectionTimeRange = (timeValue, timeValue); return true; } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index e771a9753f..a16fb52f01 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Mania.Edit { public class ManiaBeatSnapGrid : Component { - private const double visible_range = 1500; + private const double visible_range = 750; [Resolved] private IManiaHitObjectComposer composer { get; set; } @@ -44,6 +45,34 @@ namespace osu.Game.Rulesets.Mania.Edit private readonly List grids = new List(); + private readonly Cached lineCache = new Cached(); + + private (double start, double end)? selectionTimeRange; + + public (double start, double end)? SelectionTimeRange + { + get => selectionTimeRange; + set + { + if (value == selectionTimeRange) + return; + + selectionTimeRange = value; + lineCache.Invalidate(); + } + } + + protected override void Update() + { + base.Update(); + + if (!lineCache.IsValid) + { + lineCache.Validate(); + createLines(); + } + } + [BackgroundDependencyLoader] private void load() { @@ -61,49 +90,65 @@ namespace osu.Game.Rulesets.Mania.Edit beatDivisor.BindValueChanged(_ => createLines(), true); } - public override void Hide() - { - base.Hide(); - foreach (var grid in grids) - grid.Hide(); - } - - public override void Show() - { - base.Show(); - foreach (var grid in grids) - grid.Show(); - } - private void createLines() { foreach (var grid in grids) grid.Clear(); - for (int i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++) + if (selectionTimeRange == null) + return; + + var range = selectionTimeRange.Value; + + var timingPoint = beatmap.ControlPointInfo.TimingPointAt(range.start - visible_range); + + double time = timingPoint.Time; + int beat = 0; + + // progress time until in the visible range. + while (time < range.start - visible_range) { - var point = beatmap.ControlPointInfo.TimingPoints[i]; - var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : working.Value.Track.Length; + time += timingPoint.BeatLength / beatDivisor.Value; + beat++; + } - int beat = 0; + while (time < range.end + visible_range) + { + var nextTimingPoint = beatmap.ControlPointInfo.TimingPointAt(time); - for (double t = point.Time; t < until; t += point.BeatLength / beatDivisor.Value) + // switch to the next timing point if we have reached it. + if (nextTimingPoint != timingPoint) { - var indexInBeat = beat % beatDivisor.Value; - Color4 colour; + beat = 0; + timingPoint = nextTimingPoint; + } - if (indexInBeat == 0) - colour = BindableBeatDivisor.GetColourFor(1, colours); + Color4 colour = BindableBeatDivisor.GetColourFor( + BindableBeatDivisor.GetDivisorForBeatIndex(Math.Max(1, beat), beatDivisor.Value), colours); + + foreach (var grid in grids) + grid.Add(new DrawableGridLine(time, colour)); + + beat++; + time += timingPoint.BeatLength / beatDivisor.Value; + } + + foreach (var grid in grids) + { + // required to update ScrollingHitObjectContainer's cache. + grid.UpdateSubTree(); + + foreach (var line in grid.Objects.OfType()) + { + time = line.HitObject.StartTime; + + if (time >= range.start && time <= range.end) + line.Alpha = 1; else { - var divisor = BindableBeatDivisor.GetDivisorForBeatIndex(beat, beatDivisor.Value); - colour = BindableBeatDivisor.GetColourFor(divisor, colours); + double timeSeparation = time < range.start ? range.start - time : time - range.end; + line.Alpha = (float)Math.Max(0, 1 - timeSeparation / visible_range); } - - foreach (var grid in grids) - grid.Add(new DrawableGridLine(t, colour)); - - beat++; } } } @@ -112,6 +157,7 @@ namespace osu.Game.Rulesets.Mania.Edit { float minDist = float.PositiveInfinity; DrawableGridLine minDistLine = null; + Vector2 minDistLinePosition = Vector2.Zero; foreach (var grid in grids) @@ -137,33 +183,6 @@ namespace osu.Game.Rulesets.Mania.Edit return (new Vector2(position.X, minDistLinePosition.Y + noteOffset), minDistLine.HitObject.StartTime); } - public void SetRange(double minTime, double maxTime) - { - if (LoadState >= LoadState.Ready) - setRange(minTime, maxTime); - else - Schedule(() => setRange(minTime, maxTime)); - } - - private void setRange(double minTime, double maxTime) - { - foreach (var grid in grids) - { - foreach (var line in grid.Objects.OfType()) - { - double lineTime = line.HitObject.StartTime; - - if (lineTime >= minTime && lineTime <= maxTime) - line.Colour = Color4.White; - else - { - double timeSeparation = lineTime < minTime ? minTime - lineTime : lineTime - maxTime; - line.Colour = OsuColour.Gray((float)Math.Max(0, 1 - timeSeparation / visible_range)); - } - } - } - } - private class DrawableGridLine : DrawableHitObject { [Resolved] diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 1266761d12..475320ece3 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -68,18 +68,15 @@ namespace osu.Game.Rulesets.Mania.Edit { if (EditorBeatmap.SelectedHitObjects.Any()) { - beatSnapGrid.SetRange(EditorBeatmap.SelectedHitObjects.Min(h => h.StartTime), EditorBeatmap.SelectedHitObjects.Max(h => h.GetEndTime())); - beatSnapGrid.Show(); + beatSnapGrid.SelectionTimeRange = (EditorBeatmap.SelectedHitObjects.Min(h => h.StartTime), EditorBeatmap.SelectedHitObjects.Max(h => h.GetEndTime())); } else - beatSnapGrid.Hide(); + beatSnapGrid.SelectionTimeRange = null; } else { var placementTime = GetSnappedPosition(ToLocalSpace(inputManager.CurrentState.Mouse.Position), 0).time; - beatSnapGrid.SetRange(placementTime, placementTime); - - beatSnapGrid.Show(); + beatSnapGrid.SelectionTimeRange = (placementTime, placementTime); } } From d56466e2b9376318edc845c84c361fbf3927161d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 May 2020 19:07:35 +0900 Subject: [PATCH 15/27] Add very basic pooling of grid lines --- .../Edit/ManiaBeatSnapGrid.cs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index a16fb52f01..067438af39 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -90,10 +90,17 @@ namespace osu.Game.Rulesets.Mania.Edit beatDivisor.BindValueChanged(_ => createLines(), true); } + private readonly Stack availableLines = new Stack(); + private void createLines() { foreach (var grid in grids) - grid.Clear(); + { + foreach (var line in grid.Objects.OfType()) + availableLines.Push(line); + + grid.Clear(false); + } if (selectionTimeRange == null) return; @@ -127,7 +134,15 @@ namespace osu.Game.Rulesets.Mania.Edit BindableBeatDivisor.GetDivisorForBeatIndex(Math.Max(1, beat), beatDivisor.Value), colours); foreach (var grid in grids) - grid.Add(new DrawableGridLine(time, colour)); + { + if (!availableLines.TryPop(out var line)) + line = new DrawableGridLine(); + + line.HitObject.StartTime = time; + line.Colour = colour; + + grid.Add(line); + } beat++; time += timingPoint.BeatLength / beatDivisor.Value; @@ -190,17 +205,13 @@ namespace osu.Game.Rulesets.Mania.Edit private readonly IBindable direction = new Bindable(); - public DrawableGridLine(double startTime, Color4 colour) - : base(new HitObject { StartTime = startTime }) + public DrawableGridLine() + : base(new HitObject()) { RelativeSizeAxes = Axes.X; Height = 2; - AddInternal(new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colour - }); + AddInternal(new Box { RelativeSizeAxes = Axes.Both }); } [BackgroundDependencyLoader] From a6f3dc53f72e3100da0cb6d422a872522371e38e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 May 2020 23:01:36 +0900 Subject: [PATCH 16/27] Fix time value not being updated for next timing point --- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 067438af39..5803c67b80 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -127,6 +127,7 @@ namespace osu.Game.Rulesets.Mania.Edit if (nextTimingPoint != timingPoint) { beat = 0; + time = nextTimingPoint.Time; timingPoint = nextTimingPoint; } From c28a9bdb804a05ee5fac61b5728931885650cdf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 May 2020 23:02:20 +0900 Subject: [PATCH 17/27] Move load method up --- .../Edit/ManiaBeatSnapGrid.cs | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 5803c67b80..0b7834addb 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -51,7 +51,6 @@ namespace osu.Game.Rulesets.Mania.Edit public (double start, double end)? SelectionTimeRange { - get => selectionTimeRange; set { if (value == selectionTimeRange) @@ -62,17 +61,6 @@ namespace osu.Game.Rulesets.Mania.Edit } } - protected override void Update() - { - base.Update(); - - if (!lineCache.IsValid) - { - lineCache.Validate(); - createLines(); - } - } - [BackgroundDependencyLoader] private void load() { @@ -90,6 +78,17 @@ namespace osu.Game.Rulesets.Mania.Edit beatDivisor.BindValueChanged(_ => createLines(), true); } + protected override void Update() + { + base.Update(); + + if (!lineCache.IsValid) + { + lineCache.Validate(); + createLines(); + } + } + private readonly Stack availableLines = new Stack(); private void createLines() From 85156c62efd7900dbce4115e27f96327f4fd0345 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 May 2020 23:05:08 +0900 Subject: [PATCH 18/27] Add xmldoc and address some code quality concerns --- .../Edit/ManiaBeatSnapGrid.cs | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 0b7834addb..98e15e3fa8 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -21,12 +21,27 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Edit { + /// + /// A grid which displays coloured beat divisor lines in proximity to the selection or placement cursor. + /// public class ManiaBeatSnapGrid : Component { private const double visible_range = 750; - [Resolved] - private IManiaHitObjectComposer composer { get; set; } + /// + /// The range of time values of the current selection. + /// + public (double start, double end)? SelectionTimeRange + { + set + { + if (value == selectionTimeRange) + return; + + selectionTimeRange = value; + lineCache.Invalidate(); + } + } [Resolved] private EditorBeatmap beatmap { get; set; } @@ -49,20 +64,8 @@ namespace osu.Game.Rulesets.Mania.Edit private (double start, double end)? selectionTimeRange; - public (double start, double end)? SelectionTimeRange - { - set - { - if (value == selectionTimeRange) - return; - - selectionTimeRange = value; - lineCache.Invalidate(); - } - } - [BackgroundDependencyLoader] - private void load() + private void load(IManiaHitObjectComposer composer) { foreach (var stage in composer.Playfield.Stages) { From da8729e6bde39ec4255d498cde1e50a7135d5601 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 19 May 2020 23:28:42 +0900 Subject: [PATCH 19/27] 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 650ebde54d..f0f16d3763 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 ee6206e166..010ef8578a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index cbf8600c62..88b0c7dd8a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -80,7 +80,7 @@ - + From d31a59b07466eae570e1127624c30286666339b4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 May 2020 14:55:36 +0900 Subject: [PATCH 20/27] Fix logic results in infinite loop on default timing point return --- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 98e15e3fa8..05990eadd7 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Mania.Edit var nextTimingPoint = beatmap.ControlPointInfo.TimingPointAt(time); // switch to the next timing point if we have reached it. - if (nextTimingPoint != timingPoint) + if (nextTimingPoint.Time > timingPoint.Time) { beat = 0; time = nextTimingPoint.Time; From 0bc3073d49aeff5ed5647fca342f158725222510 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 May 2020 15:01:32 +0900 Subject: [PATCH 21/27] Fix test failures --- .../TestSceneManiaHitObjectComposer.cs | 14 +++++++++----- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectComposer.cs index 6274bb1005..bad3d7854e 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaHitObjectComposer.cs @@ -42,6 +42,7 @@ namespace osu.Game.Rulesets.Mania.Tests public void TestDragOffscreenSelectionVerticallyUpScroll() { DrawableHitObject lastObject = null; + double originalTime = 0; Vector2 originalPosition = Vector2.Zero; setScrollStep(ScrollingDirection.Up); @@ -49,6 +50,7 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("seek to last object", () => { lastObject = this.ChildrenOfType().Single(d => d.HitObject == composer.EditorBeatmap.HitObjects.Last()); + originalTime = lastObject.HitObject.StartTime; Clock.Seek(composer.EditorBeatmap.HitObjects.Last().StartTime); }); @@ -64,19 +66,20 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("move mouse downwards", () => { - InputManager.MoveMouseTo(lastObject, new Vector2(0, 20)); + InputManager.MoveMouseTo(lastObject, new Vector2(0, lastObject.ScreenSpaceDrawQuad.Height * 2)); InputManager.ReleaseButton(MouseButton.Left); }); AddAssert("hitobjects not moved columns", () => composer.EditorBeatmap.HitObjects.All(h => ((ManiaHitObject)h).Column == 0)); AddAssert("hitobjects moved downwards", () => lastObject.DrawPosition.Y - originalPosition.Y > 0); - AddAssert("hitobjects not moved too far", () => lastObject.DrawPosition.Y - originalPosition.Y < 50); + AddAssert("hitobject has moved time", () => lastObject.HitObject.StartTime == originalTime + 125); } [Test] public void TestDragOffscreenSelectionVerticallyDownScroll() { DrawableHitObject lastObject = null; + double originalTime = 0; Vector2 originalPosition = Vector2.Zero; setScrollStep(ScrollingDirection.Down); @@ -84,6 +87,7 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("seek to last object", () => { lastObject = this.ChildrenOfType().Single(d => d.HitObject == composer.EditorBeatmap.HitObjects.Last()); + originalTime = lastObject.HitObject.StartTime; Clock.Seek(composer.EditorBeatmap.HitObjects.Last().StartTime); }); @@ -99,13 +103,13 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("move mouse upwards", () => { - InputManager.MoveMouseTo(lastObject, new Vector2(0, -20)); + InputManager.MoveMouseTo(lastObject, new Vector2(0, -lastObject.ScreenSpaceDrawQuad.Height * 2)); InputManager.ReleaseButton(MouseButton.Left); }); AddAssert("hitobjects not moved columns", () => composer.EditorBeatmap.HitObjects.All(h => ((ManiaHitObject)h).Column == 0)); AddAssert("hitobjects moved upwards", () => originalPosition.Y - lastObject.DrawPosition.Y > 0); - AddAssert("hitobjects not moved too far", () => originalPosition.Y - lastObject.DrawPosition.Y < 50); + AddAssert("hitobject has moved time", () => lastObject.HitObject.StartTime == originalTime + 125); } [Test] @@ -207,7 +211,7 @@ namespace osu.Game.Rulesets.Mania.Tests }; for (int i = 0; i < 10; i++) - EditorBeatmap.Add(new Note { StartTime = 100 * i }); + EditorBeatmap.Add(new Note { StartTime = 125 * i }); } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index 05990eadd7..fa8f8a755a 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -180,7 +180,7 @@ namespace osu.Game.Rulesets.Mania.Edit foreach (var grid in grids) { - foreach (var line in grid.AliveObjects.OfType()) + foreach (var line in grid.Objects.OfType()) { Vector2 linePos = line.ToSpaceOfOtherDrawable(line.OriginPosition, this); float d = Vector2.Distance(position, linePos); From 83a5913b8d7a4ddb3adc9610b39e3e5e28041933 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 21 May 2020 12:11:39 +0900 Subject: [PATCH 22/27] Undo beat snapping related changes --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 16 ++-------------- .../Edit/ManiaHitObjectComposer.cs | 17 +++++------------ 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 184356b89c..3fb03d642f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -24,15 +24,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected Column Column; /// - /// The current beat-snapped mouse position, snapped to the closest column. + /// The current mouse position, snapped to the closest column. /// protected Vector2 SnappedMousePosition { get; private set; } - /// - /// The gameplay time at the current beat-snapped mouse position (). - /// - protected double SnappedTime { get; private set; } - /// /// The width of the closest column to the current mouse position. /// @@ -44,9 +39,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } - [Resolved(CanBeNull = true)] - private IDistanceSnapProvider snapProvider { get; set; } - protected ManiaPlacementBlueprint(T hitObject) : base(hitObject) { @@ -62,7 +54,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints return base.OnMouseDown(e); HitObject.Column = Column.Index; - BeginPlacement(SnappedTime, true); + BeginPlacement(TimeAt(e.ScreenSpaceMousePosition), true); return true; } @@ -78,10 +70,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints // Snap to the column var parentPos = Parent.ToLocalSpace(Column.ToScreenSpace(new Vector2(Column.DrawWidth / 2, 0))); SnappedMousePosition = new Vector2(parentPos.X, Parent.ToLocalSpace(screenSpacePosition).Y); - - SnappedTime = TimeAt(screenSpacePosition); - if (snapProvider != null) - (SnappedMousePosition, SnappedTime) = snapProvider.GetSnappedPosition(SnappedMousePosition, SnappedTime); } protected double TimeAt(Vector2 screenSpacePosition) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 475320ece3..7677ac6f07 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -82,18 +82,9 @@ namespace osu.Game.Rulesets.Mania.Edit public override (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) { - var beatSnapped = beatSnapGrid.GetSnappedPosition(position); + var hoc = Playfield.GetColumn(0).HitObjectContainer; - if (beatSnapped != null) - return beatSnapped.Value; - - return base.GetSnappedPosition(position, getTimeFromPosition(ToScreenSpace(position))); - } - - private double getTimeFromPosition(Vector2 screenSpacePosition) - { - var hoc = Playfield.Stages[0].HitObjectContainer; - float targetPosition = hoc.ToLocalSpace(screenSpacePosition).Y; + float targetPosition = hoc.ToLocalSpace(ToScreenSpace(position)).Y; if (drawableRuleset.ScrollingInfo.Direction.Value == ScrollingDirection.Down) { @@ -103,10 +94,12 @@ namespace osu.Game.Rulesets.Mania.Edit targetPosition = hoc.DrawHeight - targetPosition; } - return drawableRuleset.ScrollingInfo.Algorithm.TimeAt(targetPosition, + double targetTime = drawableRuleset.ScrollingInfo.Algorithm.TimeAt(targetPosition, EditorClock.CurrentTime, drawableRuleset.ScrollingInfo.TimeRange.Value, hoc.DrawHeight); + + return base.GetSnappedPosition(position, targetTime); } protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) From 8a105bdbcfc554f4bd62217782d01632722a047a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 11:19:57 +0900 Subject: [PATCH 23/27] Remove unused ColumnAt method --- osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs | 2 -- osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs | 9 +-------- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs | 8 -------- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs index 48e6b63064..5d9ad21cb7 100644 --- a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs @@ -8,8 +8,6 @@ namespace osu.Game.Rulesets.Mania.Edit { public interface IManiaHitObjectComposer { - Column ColumnAt(Vector2 screenSpacePosition); - ManiaPlayfield Playfield { get; } Vector2 ScreenSpacePositionAtTime(double time, Column column = null); diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 4795bdd8e2..d4cfab840d 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -44,13 +44,6 @@ namespace osu.Game.Rulesets.Mania.Edit inputManager = GetContainingInputManager(); } - /// - /// Retrieves the column that intersects a screen-space position. - /// - /// The screen-space position. - /// The column which intersects with . - public Column ColumnAt(Vector2 screenSpacePosition) => drawableRuleset.GetColumnByPosition(screenSpacePosition); - private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) @@ -85,7 +78,7 @@ namespace osu.Game.Rulesets.Mania.Edit public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) { - var column = ColumnAt(screenSpacePosition); + var column = Playfield.GetColumnByPosition(screenSpacePosition); if (column == null) return new SnapResult(screenSpacePosition, null); diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 83049ff959..4ea71652bc 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mania.Edit private void performColumnMovement(int lastColumn, MoveSelectionEvent moveEvent) { - var currentColumn = composer.ColumnAt(moveEvent.ScreenSpacePosition); + var currentColumn = composer.Playfield.GetColumnByPosition(moveEvent.ScreenSpacePosition); if (currentColumn == null) return; diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index f3f843f366..94b5ee9486 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -23,7 +23,6 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; -using osuTK; namespace osu.Game.Rulesets.Mania.UI { @@ -108,13 +107,6 @@ namespace osu.Game.Rulesets.Mania.UI private void updateTimeRange() => TimeRange.Value = configTimeRange.Value * speedAdjustmentTrack.AggregateTempo.Value * speedAdjustmentTrack.AggregateFrequency.Value; - /// - /// Retrieves the column that intersects a screen-space position. - /// - /// The screen-space position. - /// The column which intersects with . - public Column GetColumnByPosition(Vector2 screenSpacePosition) => Playfield.GetColumnByPosition(screenSpacePosition); - public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new ManiaPlayfieldAdjustmentContainer(); protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages); From 9a2889abc54d2c5217bb5adbbd591be7c8dc7d97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 11:32:35 +0900 Subject: [PATCH 24/27] Remove remaining left-over test implementations --- .../ManiaPlacementBlueprintTestScene.cs | 3 --- .../ManiaSelectionBlueprintTestScene.cs | 9 +-------- .../TestSceneManiaBeatSnapGrid.cs | 5 ----- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs index 9a50802454..fd18907d96 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestScene.cs @@ -15,7 +15,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests @@ -57,7 +56,5 @@ namespace osu.Game.Rulesets.Mania.Tests protected override void AddHitObject(DrawableHitObject hitObject) => column.Add((DrawableManiaHitObject)hitObject); public ManiaPlayfield Playfield => null; - - public Vector2 ScreenSpacePositionAtTime(double time, Column column = null) => Vector2.Zero; } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs index f7dffbbc1a..35fe596e98 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestScene.cs @@ -7,7 +7,6 @@ using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests @@ -18,11 +17,9 @@ namespace osu.Game.Rulesets.Mania.Tests [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); - private readonly Column column; - protected ManiaSelectionBlueprintTestScene() { - Add(column = new Column(0) + Add(new Column(0) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -31,10 +28,6 @@ namespace osu.Game.Rulesets.Mania.Tests }); } - public Column ColumnAt(Vector2 screenSpacePosition) => column; - public ManiaPlayfield Playfield => null; - - public Vector2 ScreenSpacePositionAtTime(double time, Column column = null) => Vector2.Zero; } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs index feda3cfb81..ce9546415f 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneManiaBeatSnapGrid.cs @@ -14,7 +14,6 @@ using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; using osu.Game.Tests.Visual; -using osuTK; namespace osu.Game.Rulesets.Mania.Tests { @@ -66,10 +65,6 @@ namespace osu.Game.Rulesets.Mania.Tests return true; } - public Column ColumnAt(Vector2 screenSpacePosition) => null; - public ManiaPlayfield Playfield { get; } - - public Vector2 ScreenSpacePositionAtTime(double time, Column column = null) => Vector2.Zero; } } From b2667bbb0210d00b9f6502362fc632f93bb9fa92 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 11:45:58 +0900 Subject: [PATCH 25/27] Move protected implementation down --- .../Edit/ManiaHitObjectComposer.cs | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 82a55b4965..683e921cbf 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -53,29 +53,6 @@ namespace osu.Game.Rulesets.Mania.Edit public IScrollingInfo ScrollingInfo => drawableRuleset.ScrollingInfo; - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - if (BlueprintContainer.CurrentTool is SelectTool) - { - if (EditorBeatmap.SelectedHitObjects.Any()) - { - beatSnapGrid.SelectionTimeRange = (EditorBeatmap.SelectedHitObjects.Min(h => h.StartTime), EditorBeatmap.SelectedHitObjects.Max(h => h.GetEndTime())); - } - else - beatSnapGrid.SelectionTimeRange = null; - } - else - { - var result = SnapScreenSpacePositionToValidTime(inputManager.CurrentState.Mouse.Position); - if (result.Time is double time) - beatSnapGrid.SelectionTimeRange = (time, time); - else - beatSnapGrid.SelectionTimeRange = null; - } - } - public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) { var column = Playfield.GetColumnByPosition(screenSpacePosition); @@ -111,5 +88,28 @@ namespace osu.Game.Rulesets.Mania.Edit new NoteCompositionTool(), new HoldNoteCompositionTool() }; + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + if (BlueprintContainer.CurrentTool is SelectTool) + { + if (EditorBeatmap.SelectedHitObjects.Any()) + { + beatSnapGrid.SelectionTimeRange = (EditorBeatmap.SelectedHitObjects.Min(h => h.StartTime), EditorBeatmap.SelectedHitObjects.Max(h => h.GetEndTime())); + } + else + beatSnapGrid.SelectionTimeRange = null; + } + else + { + var result = SnapScreenSpacePositionToValidTime(inputManager.CurrentState.Mouse.Position); + if (result.Time is double time) + beatSnapGrid.SelectionTimeRange = (time, time); + else + beatSnapGrid.SelectionTimeRange = null; + } + } } } From d529a2aefac633bde0bcdf32e215e0d89af7bff6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 12:28:01 +0900 Subject: [PATCH 26/27] Remove left-over function --- .../Edit/ManiaBeatSnapGrid.cs | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index fa8f8a755a..e52cd5774c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -11,12 +11,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Edit @@ -171,36 +169,6 @@ namespace osu.Game.Rulesets.Mania.Edit } } - public (Vector2 position, double time)? GetSnappedPosition(Vector2 position) - { - float minDist = float.PositiveInfinity; - DrawableGridLine minDistLine = null; - - Vector2 minDistLinePosition = Vector2.Zero; - - foreach (var grid in grids) - { - foreach (var line in grid.Objects.OfType()) - { - Vector2 linePos = line.ToSpaceOfOtherDrawable(line.OriginPosition, this); - float d = Vector2.Distance(position, linePos); - - if (d < minDist) - { - minDist = d; - minDistLine = line; - minDistLinePosition = linePos; - } - } - } - - if (minDistLine == null) - return null; - - float noteOffset = (scrollingInfo.Direction.Value == ScrollingDirection.Up ? 1 : -1) * DefaultNotePiece.NOTE_HEIGHT / 2; - return (new Vector2(position.X, minDistLinePosition.Y + noteOffset), minDistLine.HitObject.StartTime); - } - private class DrawableGridLine : DrawableHitObject { [Resolved] From ce35d09e7dac2987f3cb439366eba75e0db0d7a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 22 May 2020 12:45:37 +0900 Subject: [PATCH 27/27] Fix incorrect alpha application to lines on rewinding --- osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs | 8 ++++++-- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs index e52cd5774c..b5b6c08fca 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaBeatSnapGrid.cs @@ -199,10 +199,14 @@ namespace osu.Game.Rulesets.Mania.Edit : Anchor.BottomLeft; } + protected override void UpdateInitialTransforms() + { + // don't perform any fading – we are handling that ourselves. + } + protected override void UpdateStateTransforms(ArmedState state) { - using (BeginAbsoluteSequence(HitObject.StartTime + 1000)) - this.FadeOut(); + LifetimeEnd = HitObject.StartTime + visible_range; } } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index d594909cda..44afb7a227 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -257,7 +257,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } } - if (state.Value != ArmedState.Idle && LifetimeEnd == double.MaxValue || HitObject.HitWindows == null) + if (LifetimeEnd == double.MaxValue && (state.Value != ArmedState.Idle || HitObject.HitWindows == null)) Expire(); // apply any custom state overrides