From 3a1fee59fbf6af189b4987fa6612e2916113430e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Nov 2018 18:24:18 +0900 Subject: [PATCH 01/39] Implement note placement --- .../TestCaseColumn.cs | 8 +- .../Edit/Blueprints/NotePlacementBlueprint.cs | 74 +++++++++++++++++++ .../Edit/ManiaHitObjectComposer.cs | 11 ++- .../Edit/NoteCompositionTool.cs | 20 +++++ osu.Game.Rulesets.Mania/UI/Column.cs | 9 ++- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 27 +++++++ osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 2 +- .../Rulesets/Edit/EditRulesetContainer.cs | 4 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 24 +++--- .../Tests/Visual/ScrollingTestContainer.cs | 3 + 10 files changed, 160 insertions(+), 22 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs index d044b48553..63724f8edf 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseColumn.cs @@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Mania.Tests Spacing = new Vector2(20, 0), Children = new[] { - createColumn(ScrollingDirection.Up, ManiaAction.Key1), - createColumn(ScrollingDirection.Down, ManiaAction.Key2) + createColumn(ScrollingDirection.Up, ManiaAction.Key1, 0), + createColumn(ScrollingDirection.Down, ManiaAction.Key2, 1) } }; } @@ -85,9 +85,9 @@ namespace osu.Game.Rulesets.Mania.Tests } } - private Drawable createColumn(ScrollingDirection direction, ManiaAction action) + private Drawable createColumn(ScrollingDirection direction, ManiaAction action, int index) { - var column = new Column + var column = new Column(index) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs new file mode 100644 index 0000000000..7102d328ec --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -0,0 +1,74 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints +{ + public class NotePlacementBlueprint : PlacementBlueprint + { + protected new Note HitObject => (Note)base.HitObject; + + [Resolved] + private ManiaHitObjectComposer composer { get; set; } + + [Resolved] + private IScrollingInfo scrollingInfo { get; set; } + + public NotePlacementBlueprint() + : base(new Note()) + { + RelativeSizeAxes = Axes.None; + + Origin = Anchor.Centre; + + AutoSizeAxes = Axes.Y; + Width = 45; + + InternalChild = new EditNotePiece { RelativeSizeAxes = Axes.X }; + } + + protected override bool OnMouseMove(MouseMoveEvent e) + { + Position = e.MousePosition; + return true; + } + + protected override bool OnClick(ClickEvent e) + { + var offsetPosition = e.ScreenSpaceMousePosition; + switch (scrollingInfo.Direction.Value) + { + case ScrollingDirection.Up: + offsetPosition.Y -= DrawHeight / 2; + break; + case ScrollingDirection.Down: + offsetPosition.Y += DrawHeight / 2; + break; + } + + var column = composer.ColumnAt(offsetPosition); + if (column == null) + return base.OnClick(e); + + var hitObjectContainer = column.HitObjectContainer; + + HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(hitObjectContainer.ToLocalSpace(offsetPosition).Y, + EditorClock.CurrentTime, + scrollingInfo.TimeRange.Value, + hitObjectContainer.DrawHeight); + + HitObject.Column = column.Index; + + EndPlacement(); + + return true; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 3531b81e68..33e52b1737 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; @@ -11,10 +10,13 @@ using osu.Game.Rulesets.Objects.Drawables; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Edit.Blueprints; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI; +using OpenTK; namespace osu.Game.Rulesets.Mania.Edit { + [Cached] public class ManiaHitObjectComposer : HitObjectComposer { public ManiaHitObjectComposer(Ruleset ruleset) @@ -27,6 +29,8 @@ namespace osu.Game.Rulesets.Mania.Edit protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + public Column ColumnAt(Vector2 screenSpacePosition) => ((ManiaPlayfield)RulesetContainer.Playfield).GetColumnByPosition(screenSpacePosition); + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) { var rulesetContainer = new ManiaEditRulesetContainer(ruleset, beatmap); @@ -37,7 +41,10 @@ namespace osu.Game.Rulesets.Mania.Edit return rulesetContainer; } - protected override IReadOnlyList CompositionTools => Array.Empty(); + protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] + { + new NoteCompositionTool() + }; public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) { diff --git a/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs new file mode 100644 index 0000000000..93f49d1cc0 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/NoteCompositionTool.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Mania.Edit.Blueprints; +using osu.Game.Rulesets.Mania.Objects; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class NoteCompositionTool : HitObjectCompositionTool + { + public NoteCompositionTool() + : base(nameof(Note)) + { + } + + public override PlacementBlueprint CreatePlacementBlueprint() => new NotePlacementBlueprint(); + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 576af6d93a..da3ee8dddf 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -21,6 +21,11 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; + /// + /// The index of this column as part of the whole playfield. + /// + public readonly int Index; + public readonly Bindable Action = new Bindable(); private readonly ColumnBackground background; @@ -30,8 +35,10 @@ namespace osu.Game.Rulesets.Mania.UI internal readonly Container TopLevelContainer; private readonly Container explosionContainer; - public Column() + public Column(int index) { + Index = index; + RelativeSizeAxes = Axes.Y; Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index c59917056d..410c6aa908 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -54,6 +54,33 @@ namespace osu.Game.Rulesets.Mania.UI public void Add(BarLine barline) => stages.ForEach(s => s.Add(barline)); + /// + /// Retrieves a column from a screen-space position. + /// + /// The screen-space position. + /// The column which the lies in. + public Column GetColumnByPosition(Vector2 screenSpacePosition) + { + Column found = null; + + foreach (var stage in stages) + { + foreach (var column in stage.Columns) + { + if (column.ReceivePositionalInputAt(screenSpacePosition)) + { + found = column; + break; + } + } + + if (found != null) + break; + } + + return found; + } + private ManiaStage getStageByColumn(int column) { int sum = 0; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 19e930f530..d1ce8b8679 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.Mania.UI for (int i = 0; i < definition.Columns; i++) { var isSpecial = definition.IsSpecialColumn(i); - var column = new Column + var column = new Column(firstColumnIndex + i) { IsSpecial = isSpecial, Action = { Value = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ } diff --git a/osu.Game/Rulesets/Edit/EditRulesetContainer.cs b/osu.Game/Rulesets/Edit/EditRulesetContainer.cs index bc54c907ab..3c493eb16f 100644 --- a/osu.Game/Rulesets/Edit/EditRulesetContainer.cs +++ b/osu.Game/Rulesets/Edit/EditRulesetContainer.cs @@ -68,9 +68,9 @@ namespace osu.Game.Rulesets.Edit // Process object var processor = ruleset.CreateBeatmapProcessor(beatmap); - processor.PreProcess(); + processor?.PreProcess(); tObject.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty); - processor.PostProcess(); + processor?.PostProcess(); // Add visual representation var drawableObject = rulesetContainer.GetVisualRepresentation(tObject); diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 485c1921cf..0afe33ff2e 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Edit { public abstract class HitObjectComposer : CompositeDrawable { - public IEnumerable HitObjects => rulesetContainer.Playfield.AllHitObjects; + public IEnumerable HitObjects => RulesetContainer.Playfield.AllHitObjects; protected readonly Ruleset Ruleset; @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Edit private readonly List layerContainers = new List(); - private EditRulesetContainer rulesetContainer; + protected EditRulesetContainer RulesetContainer { get; private set; } private BlueprintContainer blueprintContainer; @@ -51,8 +51,8 @@ namespace osu.Game.Rulesets.Edit try { - rulesetContainer = CreateRulesetContainer(); - rulesetContainer.Clock = framedClock; + RulesetContainer = CreateRulesetContainer(); + RulesetContainer.Clock = framedClock; } catch (Exception e) { @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Edit layerBelowRuleset.Child = new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both }; var layerAboveRuleset = CreateLayerContainer(); - layerAboveRuleset.Child = new BlueprintContainer(); + layerAboveRuleset.Child = blueprintContainer = new BlueprintContainer(); layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerAboveRuleset); @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Edit Children = new Drawable[] { layerBelowRuleset, - rulesetContainer, + RulesetContainer, layerAboveRuleset } } @@ -130,10 +130,10 @@ namespace osu.Game.Rulesets.Edit layerContainers.ForEach(l => { - l.Anchor = rulesetContainer.Playfield.Anchor; - l.Origin = rulesetContainer.Playfield.Origin; - l.Position = rulesetContainer.Playfield.Position; - l.Size = rulesetContainer.Playfield.Size; + l.Anchor = RulesetContainer.Playfield.Anchor; + l.Origin = RulesetContainer.Playfield.Origin; + l.Position = RulesetContainer.Playfield.Position; + l.Size = RulesetContainer.Playfield.Size; }); } @@ -141,9 +141,9 @@ namespace osu.Game.Rulesets.Edit /// Adds a to the and visualises it. /// /// The to add. - public void Add(HitObject hitObject) => blueprintContainer.AddBlueprintFor(rulesetContainer.Add(hitObject)); + public void Add(HitObject hitObject) => blueprintContainer.AddBlueprintFor(RulesetContainer.Add(hitObject)); - public void Remove(HitObject hitObject) => blueprintContainer.RemoveBlueprintFor(rulesetContainer.Remove(hitObject)); + public void Remove(HitObject hitObject) => blueprintContainer.RemoveBlueprintFor(RulesetContainer.Remove(hitObject)); internal abstract EditRulesetContainer CreateRulesetContainer(); diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs index 18b29345c1..1819fdb2a0 100644 --- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs +++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs @@ -85,6 +85,9 @@ namespace osu.Game.Tests.Visual public float PositionAt(double time, double currentTime, double timeRange, float scrollLength) => implementation.PositionAt(time, currentTime, timeRange, scrollLength); + public double TimeAt(float position, double currentTime, double timeRange, float scrollLength) + => implementation.TimeAt(position, currentTime, timeRange, scrollLength); + public void Reset() => implementation.Reset(); } From 1d40a042f6ff8da4bc14b1c6997c092140febba3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Nov 2018 18:32:44 +0900 Subject: [PATCH 02/39] Extract common methods into ManiaPlacementBlueprint --- .../Blueprints/ManiaPlacementBlueprint.cs | 61 +++++++++++++++++++ .../Edit/Blueprints/NotePlacementBlueprint.cs | 39 ++---------- 2 files changed, 66 insertions(+), 34 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs new file mode 100644 index 0000000000..402a124f01 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints +{ + public class ManiaPlacementBlueprint : PlacementBlueprint + where T : ManiaHitObject + { + protected new T HitObject => (T)base.HitObject; + + [Resolved] + private ManiaHitObjectComposer composer { get; set; } + + [Resolved] + private IScrollingInfo scrollingInfo { get; set; } + + public ManiaPlacementBlueprint(T hitObject) + : base(hitObject) + { + RelativeSizeAxes = Axes.None; + } + + protected double TimeAt(Vector2 screenSpacePosition) + { + var column = ColumnAt(screenSpacePosition); + if (column == null) + return 0; + + return scrollingInfo.Algorithm.TimeAt(column.HitObjectContainer.ToLocalSpace(applyPositionOffset(screenSpacePosition)).Y, + EditorClock.CurrentTime, + scrollingInfo.TimeRange.Value, + column.HitObjectContainer.DrawHeight); + } + + protected Column ColumnAt(Vector2 screenSpacePosition) + => composer.ColumnAt(applyPositionOffset(screenSpacePosition)); + + private Vector2 applyPositionOffset(Vector2 position) + { + switch (scrollingInfo.Direction.Value) + { + case ScrollingDirection.Up: + position.Y -= DrawHeight / 2; + break; + case ScrollingDirection.Down: + position.Y += DrawHeight / 2; + break; + } + + return position; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index 7102d328ec..1549b0ae45 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -1,31 +1,19 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class NotePlacementBlueprint : PlacementBlueprint + public class NotePlacementBlueprint : ManiaPlacementBlueprint { - protected new Note HitObject => (Note)base.HitObject; - - [Resolved] - private ManiaHitObjectComposer composer { get; set; } - - [Resolved] - private IScrollingInfo scrollingInfo { get; set; } - public NotePlacementBlueprint() : base(new Note()) { - RelativeSizeAxes = Axes.None; - Origin = Anchor.Centre; AutoSizeAxes = Axes.Y; @@ -42,28 +30,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected override bool OnClick(ClickEvent e) { - var offsetPosition = e.ScreenSpaceMousePosition; - switch (scrollingInfo.Direction.Value) - { - case ScrollingDirection.Up: - offsetPosition.Y -= DrawHeight / 2; - break; - case ScrollingDirection.Down: - offsetPosition.Y += DrawHeight / 2; - break; - } - - var column = composer.ColumnAt(offsetPosition); - if (column == null) + Column column; + if ((column = ColumnAt(e.ScreenSpaceMousePosition)) == null) return base.OnClick(e); - var hitObjectContainer = column.HitObjectContainer; - - HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(hitObjectContainer.ToLocalSpace(offsetPosition).Y, - EditorClock.CurrentTime, - scrollingInfo.TimeRange.Value, - hitObjectContainer.DrawHeight); - + HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); HitObject.Column = column.Index; EndPlacement(); From 1403fa26cfdc9f3101d1f6fdd6ea1faf85586a95 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Nov 2018 19:40:57 +0900 Subject: [PATCH 03/39] Fix placement not working correctly for downwards scroll --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 402a124f01..a7e84a97da 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -34,10 +34,18 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints if (column == null) return 0; - return scrollingInfo.Algorithm.TimeAt(column.HitObjectContainer.ToLocalSpace(applyPositionOffset(screenSpacePosition)).Y, + var hitObjectContainer = column.HitObjectContainer; + + // If we're scrolling downwards, a position of 0 is actually further away from the hit target + // so we need to flip the vertical coordinate in the hitobject container's space + var hitObjectPos = column.HitObjectContainer.ToLocalSpace(applyPositionOffset(screenSpacePosition)).Y; + if (scrollingInfo.Direction.Value == ScrollingDirection.Down) + hitObjectPos = hitObjectContainer.DrawHeight - hitObjectPos; + + return scrollingInfo.Algorithm.TimeAt(hitObjectPos, EditorClock.CurrentTime, scrollingInfo.TimeRange.Value, - column.HitObjectContainer.DrawHeight); + hitObjectContainer.DrawHeight); } protected Column ColumnAt(Vector2 screenSpacePosition) From 3d8ef97e81053501bb7c7b9e3faba9dbeda90f68 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 12 Nov 2018 19:41:06 +0900 Subject: [PATCH 04/39] Add testcase --- .../ManiaPlacementBlueprintTestCase.cs | 50 +++++++++++++++++++ .../TestCaseNotePlacementBlueprint.cs | 18 +++++++ .../Blueprints/ManiaPlacementBlueprint.cs | 2 +- .../Edit/IManiaHitObjectComposer.cs | 13 +++++ .../Edit/ManiaHitObjectComposer.cs | 4 +- .../Visual/PlacementBlueprintTestCase.cs | 14 +++--- .../Tests/Visual/ScrollingTestContainer.cs | 2 + 7 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs new file mode 100644 index 0000000000..0c87978f15 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; +using osu.Game.Rulesets.Mania.Edit; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Tests.Visual; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [Cached(Type = typeof(IManiaHitObjectComposer))] + public abstract class ManiaPlacementBlueprintTestCase : PlacementBlueprintTestCase, IManiaHitObjectComposer + { + private readonly Column column; + + protected ManiaPlacementBlueprintTestCase() + { + Add(column = new Column(0) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AccentColour = Color4.OrangeRed, + Clock = new FramedClock(new StopwatchClock()), // No scroll + }); + } + + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + + dependencies.CacheAs(((ScrollingTestContainer)HitObjectContainer).ScrollingInfo); + + return dependencies; + } + + protected override Container CreateHitObjectContainer() => new ScrollingTestContainer(ScrollingDirection.Down) { RelativeSizeAxes = Axes.Both }; + + protected override void AddHitObject(DrawableHitObject hitObject) => column.Add((DrawableManiaHitObject)hitObject); + + public Column ColumnAt(Vector2 screenSpacePosition) => column; + } +} diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs new file mode 100644 index 0000000000..9ae49d200e --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotePlacementBlueprint.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Edit.Blueprints; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public class TestCaseNotePlacementBlueprint : ManiaPlacementBlueprintTestCase + { + protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableNote((Note)hitObject); + protected override PlacementBlueprint CreateBlueprint() => new NotePlacementBlueprint(); + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index a7e84a97da..305c92671f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected new T HitObject => (T)base.HitObject; [Resolved] - private ManiaHitObjectComposer composer { get; set; } + private IManiaHitObjectComposer composer { get; set; } [Resolved] private IScrollingInfo scrollingInfo { get; set; } diff --git a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs new file mode 100644 index 0000000000..6347370d72 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mania.UI; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public interface IManiaHitObjectComposer + { + Column ColumnAt(Vector2 screenSpacePosition); + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 33e52b1737..07684f9eb8 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -16,8 +16,8 @@ using OpenTK; namespace osu.Game.Rulesets.Mania.Edit { - [Cached] - public class ManiaHitObjectComposer : HitObjectComposer + [Cached(Type = typeof(IManiaHitObjectComposer))] + public class ManiaHitObjectComposer : HitObjectComposer, IManiaHitObjectComposer { public ManiaHitObjectComposer(Ruleset ruleset) : base(ruleset) diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs index f893d8456b..ca762c6be2 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestCase.cs @@ -15,18 +15,14 @@ namespace osu.Game.Tests.Visual [Cached(Type = typeof(IPlacementHandler))] public abstract class PlacementBlueprintTestCase : OsuTestCase, IPlacementHandler { - private readonly Container hitObjectContainer; + protected readonly Container HitObjectContainer; private PlacementBlueprint currentBlueprint; protected PlacementBlueprintTestCase() { Beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize = 2; - Add(hitObjectContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Clock = new FramedClock(new StopwatchClock()) - }); + Add(HitObjectContainer = CreateHitObjectContainer()); } [BackgroundDependencyLoader] @@ -49,7 +45,7 @@ namespace osu.Game.Tests.Visual public void EndPlacement(HitObject hitObject) { - hitObjectContainer.Add(CreateHitObject(hitObject)); + AddHitObject(CreateHitObject(hitObject)); Remove(currentBlueprint); Add(currentBlueprint = CreateBlueprint()); @@ -59,6 +55,10 @@ namespace osu.Game.Tests.Visual { } + protected virtual Container CreateHitObjectContainer() => new Container { RelativeSizeAxes = Axes.Both }; + + protected virtual void AddHitObject(DrawableHitObject hitObject) => HitObjectContainer.Add(hitObject); + protected abstract DrawableHitObject CreateHitObject(HitObject hitObject); protected abstract PlacementBlueprint CreateBlueprint(); } diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs index 1819fdb2a0..bc251fddbe 100644 --- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs +++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs @@ -24,6 +24,8 @@ namespace osu.Game.Tests.Visual public double TimeRange { set => scrollingInfo.TimeRange.Value = value; } + public IScrollingInfo ScrollingInfo => scrollingInfo; + [Cached(Type = typeof(IScrollingInfo))] private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); From 25101ecd2cfaf0634a6c4f65b1933d770f53c2a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 13 Nov 2018 14:13:29 +0900 Subject: [PATCH 05/39] Snap placement blueprint to columns --- .../Blueprints/ManiaPlacementBlueprint.cs | 32 +++++++++++++++++++ .../Edit/Blueprints/NotePlacementBlueprint.cs | 7 ++-- osu.Game.Rulesets.Mania/UI/Column.cs | 5 +++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 305c92671f..bfa07d0014 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -3,6 +3,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Framework.Threading; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.UI; @@ -16,6 +18,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { protected new T HitObject => (T)base.HitObject; + /// + /// The current mouse position, snapped to the closest column. + /// + protected Vector2 SnappedMousePosition { get; private set; } + [Resolved] private IManiaHitObjectComposer composer { get; set; } @@ -28,6 +35,31 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints RelativeSizeAxes = Axes.None; } + protected override bool OnMouseMove(MouseMoveEvent e) + { + updateSnappedPosition(e); + return true; + } + + private ScheduledDelegate scheduledSnappedPositionUpdate; + + private void updateSnappedPosition(MouseMoveEvent e) + { + scheduledSnappedPositionUpdate?.Cancel(); + scheduledSnappedPositionUpdate = Schedule(() => + { + Column column = ColumnAt(e.ScreenSpaceMousePosition); + if (column == null) + SnappedMousePosition = e.MousePosition; + else + { + // Snap to the column + var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); + SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); + } + }); + } + protected double TimeAt(Vector2 screenSpacePosition) { var column = ColumnAt(screenSpacePosition); diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index 1549b0ae45..0a904d962e 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -22,10 +22,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints InternalChild = new EditNotePiece { RelativeSizeAxes = Axes.X }; } - protected override bool OnMouseMove(MouseMoveEvent e) + protected override void Update() { - Position = e.MousePosition; - return true; + base.Update(); + + Position = SnappedMousePosition; } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index da3ee8dddf..4c1929f182 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; namespace osu.Game.Rulesets.Mania.UI { @@ -172,5 +173,9 @@ namespace osu.Game.Rulesets.Mania.UI } public bool OnReleased(ManiaAction action) => false; + + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) + // This probably shouldn't exist as is, but the columns in the stage are separated by a 1px border + => DrawRectangle.Inflate(new Vector2(1, 0)).Contains(ToLocalSpace(screenSpacePos)); } } From 4dab5db2e5fd7baefece1385edf13b6907845f93 Mon Sep 17 00:00:00 2001 From: Scotsoo Date: Tue, 13 Nov 2018 17:09:28 +0000 Subject: [PATCH 06/39] Allowing keypad enter to be used along with normal enter --- osu.Game/Input/Bindings/GlobalActionContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs index 2f5f1aea3f..c58e845a6a 100644 --- a/osu.Game/Input/Bindings/GlobalActionContainer.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -43,6 +43,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(InputKey.Space, GlobalAction.Select), new KeyBinding(InputKey.Enter, GlobalAction.Select), + new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select), }; public IEnumerable InGameKeyBindings => new[] From d5464702fa16113c62d95ca2ee2f0b96021f7291 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Nov 2018 20:56:34 +0900 Subject: [PATCH 07/39] Fix post-merge issue --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b42758ebad..d41fd5c201 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Edit /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// - public virtual bool CursorInPlacementArea => rulesetContainer.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); + public virtual bool CursorInPlacementArea => RulesetContainer.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); /// /// Adds a to the and visualises it. From df7515b66ffb5854024c909a9e81da733d9d79bf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Nov 2018 21:01:06 +0900 Subject: [PATCH 08/39] Pass all selected hitobjects to the selection blueprints --- .../Edit/Blueprints/ManiaSelectionBlueprint.cs | 3 ++- .../Edit/Blueprints/OsuSelectionBlueprint.cs | 3 ++- .../Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs | 4 +++- .../Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs | 4 +++- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 3 ++- osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs | 2 +- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index 43e359cf2c..d47f43fb06 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; @@ -38,7 +39,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } - public override void AdjustPosition(DragEvent dragEvent) + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) { var objectParent = HitObject.Parent; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index 8431d5d5d0..e0dd1430fe 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; @@ -17,6 +18,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints { } - public override void AdjustPosition(DragEvent dragEvent) => OsuObject.Position += dragEvent.Delta; + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => OsuObject.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs index 4bac9d3556..aa33d4c89a 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -25,6 +27,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input. public override bool HandlePositionalInput => false; - public override void AdjustPosition(DragEvent dragEvent) => slider.Position += dragEvent.Delta; + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => slider.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index 9e9cc87c5e..f8f632535d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -21,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos); - public override void AdjustPosition(DragEvent dragEvent) + public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) { // Spinners don't support position adjustments } diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index db35d47b2b..c9d6719a92 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -134,7 +135,7 @@ namespace osu.Game.Rulesets.Edit return true; } - public abstract void AdjustPosition(DragEvent dragEvent); + public abstract void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects); /// /// The screen-space point that causes this to be selected. diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 8732672723..5d334ca559 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Edit.Compose.Components // Todo: Various forms of snapping foreach (var blueprint in selectedBlueprints) - blueprint.AdjustPosition(dragEvent); + blueprint.AdjustPosition(dragEvent, selectedBlueprints.Select(b => b.HitObject)); } protected override bool OnKeyDown(KeyDownEvent e) From f7fc2ca5697bc362b5ffceeca8de3bd58a0fea10 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 15 Nov 2018 21:37:22 +0900 Subject: [PATCH 09/39] Basic inter-column selection movement --- .../ManiaPlacementBlueprintTestCase.cs | 2 + .../ManiaSelectionBlueprintTestCase.cs | 25 ++++++++++++- .../Blueprints/ManiaSelectionBlueprint.cs | 37 +++++++++++++++++++ .../Edit/IManiaHitObjectComposer.cs | 2 + .../Edit/ManiaHitObjectComposer.cs | 2 + .../Objects/ManiaHitObject.cs | 9 ++++- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 6 +++ osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 14 ++++++- 8 files changed, 93 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs index 0c87978f15..6162d6844f 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs @@ -46,5 +46,7 @@ namespace osu.Game.Rulesets.Mania.Tests protected override void AddHitObject(DrawableHitObject hitObject) => column.Add((DrawableManiaHitObject)hitObject); public Column ColumnAt(Vector2 screenSpacePosition) => column; + + public int TotalColumns => 1; } } diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs index 8c5299e1a2..f64e54c878 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs @@ -2,14 +2,37 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Timing; +using osu.Game.Rulesets.Mania.Edit; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { - public abstract class ManiaSelectionBlueprintTestCase : SelectionBlueprintTestCase + [Cached(Type = typeof(IManiaHitObjectComposer))] + public abstract class ManiaSelectionBlueprintTestCase : SelectionBlueprintTestCase, IManiaHitObjectComposer { [Cached(Type = typeof(IAdjustableClock))] private readonly IAdjustableClock clock = new StopwatchClock(); + + private readonly Column column; + + protected ManiaSelectionBlueprintTestCase() + { + Add(column = new Column(0) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AccentColour = Color4.OrangeRed, + Clock = new FramedClock(new StopwatchClock()), // No scroll + }); + } + + public Column ColumnAt(Vector2 screenSpacePosition) => column; + + public int TotalColumns => 1; } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index d47f43fb06..ea2642ef29 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -2,11 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using OpenTK; @@ -20,6 +24,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } + [Resolved] + private IManiaHitObjectComposer composer { get; set; } + public ManiaSelectionBlueprint(DrawableHitObject hitObject) : base(hitObject) { @@ -41,6 +48,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) { + var maniaObject = (ManiaHitObject)HitObject.HitObject; + var objectParent = HitObject.Parent; // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame @@ -60,6 +69,34 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints EditorClock.CurrentTime, scrollingInfo.TimeRange.Value, objectParent.DrawHeight); + + var lastColumn = ColumnAt(dragEvent.ScreenSpaceLastMousePosition); + var currentColumn = ColumnAt(dragEvent.ScreenSpaceMousePosition); + if (lastColumn != null && currentColumn != null) + { + int columnDelta = currentColumn.Index - lastColumn.Index; + + if (columnDelta != 0) + { + int minColumn = int.MaxValue; + int maxColumn = int.MinValue; + + foreach (var obj in selectedObjects.OfType()) + { + if (obj.HitObject.Column < minColumn) + minColumn = obj.HitObject.Column; + if (obj.HitObject.Column > maxColumn) + maxColumn = obj.HitObject.Column; + } + + columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + } + + Schedule(() => maniaObject.Column += columnDelta); + } } + + protected Column ColumnAt(Vector2 screenSpacePosition) => composer.ColumnAt(screenSpacePosition); + } } diff --git a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs index 6347370d72..5b577ce2fe 100644 --- a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs @@ -9,5 +9,7 @@ namespace osu.Game.Rulesets.Mania.Edit public interface IManiaHitObjectComposer { Column ColumnAt(Vector2 screenSpacePosition); + + int TotalColumns { get; } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 07684f9eb8..01d360adfe 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -31,6 +31,8 @@ namespace osu.Game.Rulesets.Mania.Edit public Column ColumnAt(Vector2 screenSpacePosition) => ((ManiaPlayfield)RulesetContainer.Playfield).GetColumnByPosition(screenSpacePosition); + public int TotalColumns => ((ManiaPlayfield)RulesetContainer.Playfield).TotalColumns; + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) { var rulesetContainer = new ManiaEditRulesetContainer(ruleset, beatmap); diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index e183098a51..bb3d060e61 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Configuration; using osu.Game.Rulesets.Mania.Objects.Types; using osu.Game.Rulesets.Objects; @@ -8,7 +9,13 @@ namespace osu.Game.Rulesets.Mania.Objects { public abstract class ManiaHitObject : HitObject, IHasColumn { - public virtual int Column { get; set; } + public readonly Bindable ColumnBindable = new Bindable(); + + public virtual int Column + { + get => ColumnBindable; + set => ColumnBindable.Value = value; + } protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 410c6aa908..f4ea02f7e4 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -81,6 +82,11 @@ namespace osu.Game.Rulesets.Mania.UI return found; } + /// + /// Retrieves the total amount of columns across all stages in this playfield. + /// + public int TotalColumns => stages.Sum(s => s.Columns.Count); + private ManiaStage getStageByColumn(int column) { int sum = 0; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index d1ce8b8679..2730159828 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -152,8 +152,18 @@ namespace osu.Game.Rulesets.Mania.UI public override void Add(DrawableHitObject h) { var maniaObject = (ManiaHitObject)h.HitObject; - int columnIndex = maniaObject.Column - firstColumnIndex; - Columns.ElementAt(columnIndex).Add(h); + + int columnIndex = -1; + + maniaObject.ColumnBindable.BindValueChanged(_ => + { + if (columnIndex != -1) + Columns.ElementAt(columnIndex).Remove(h); + + columnIndex = maniaObject.Column - firstColumnIndex; + Columns.ElementAt(columnIndex).Add(h); + }, true); + h.OnNewResult += OnNewResult; } From 4cbda97b1eebc9ff140a6a617bb3dab821c9ec24 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 16 Nov 2018 17:12:24 +0900 Subject: [PATCH 10/39] Move positional adjustment to SelectionBox --- .../Blueprints/ManiaSelectionBlueprint.cs | 59 ------------ .../Edit/ManiaHitObjectComposer.cs | 3 + .../Edit/ManiaSelectionBox.cs | 89 +++++++++++++++++++ .../Edit/Blueprints/OsuSelectionBlueprint.cs | 4 - .../Sliders/SliderCircleSelectionBlueprint.cs | 9 -- .../Spinners/SpinnerSelectionBlueprint.cs | 8 -- .../Edit/OsuHitObjectComposer.cs | 3 + osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs | 29 ++++++ osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 3 - .../Edit/Compose/Components/SelectionBox.cs | 18 ++-- 10 files changed, 133 insertions(+), 92 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs create mode 100644 osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index ea2642ef29..05909b717f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -1,16 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using OpenTK; @@ -45,58 +39,5 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) - { - var maniaObject = (ManiaHitObject)HitObject.HitObject; - - var objectParent = HitObject.Parent; - - // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame - // without the position having been updated by the parenting ScrollingHitObjectContainer - HitObject.Y += dragEvent.Delta.Y; - - float targetPosition; - - // If we're scrolling downwards, a position of 0 is actually further away from the hit target - // so we need to flip the vertical coordinate in the hitobject container's space - if (scrollingInfo.Direction.Value == ScrollingDirection.Down) - targetPosition = -HitObject.Position.Y; - else - targetPosition = HitObject.Position.Y; - - HitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition, - EditorClock.CurrentTime, - scrollingInfo.TimeRange.Value, - objectParent.DrawHeight); - - var lastColumn = ColumnAt(dragEvent.ScreenSpaceLastMousePosition); - var currentColumn = ColumnAt(dragEvent.ScreenSpaceMousePosition); - if (lastColumn != null && currentColumn != null) - { - int columnDelta = currentColumn.Index - lastColumn.Index; - - if (columnDelta != 0) - { - int minColumn = int.MaxValue; - int maxColumn = int.MinValue; - - foreach (var obj in selectedObjects.OfType()) - { - if (obj.HitObject.Column < minColumn) - minColumn = obj.HitObject.Column; - if (obj.HitObject.Column > maxColumn) - maxColumn = obj.HitObject.Column; - } - - columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); - } - - Schedule(() => maniaObject.Column += columnDelta); - } - } - - protected Column ColumnAt(Vector2 screenSpacePosition) => composer.ColumnAt(screenSpacePosition); - } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 01d360adfe..eca70a03d4 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -12,6 +12,7 @@ using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Compose.Components; using OpenTK; namespace osu.Game.Rulesets.Mania.Edit @@ -48,6 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit new NoteCompositionTool() }; + public override SelectionBox CreateSelectionBox() => new ManiaSelectionBox(); + public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) { switch (hitObject) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs new file mode 100644 index 0000000000..83a04639eb --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs @@ -0,0 +1,89 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Input.Events; +using osu.Framework.Timing; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Screens.Edit.Compose.Components; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaSelectionBox : SelectionBox + { + [Resolved] + private IScrollingInfo scrollingInfo { get; set; } + + [Resolved] + private IManiaHitObjectComposer composer { get; set; } + + private IClock editorClock; + + [BackgroundDependencyLoader] + private void load(IAdjustableClock clock) + { + editorClock = clock; + } + + public override void HandleDrag(DragEvent dragEvent) + { + foreach (var blueprint in SelectedBlueprints) + { + var hitObject = blueprint.HitObject; + + var objectParent = hitObject.Parent; + + // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame + // without the position having been updated by the parenting ScrollingHitObjectContainer + hitObject.Y += dragEvent.Delta.Y; + + float targetPosition; + + // If we're scrolling downwards, a position of 0 is actually further away from the hit target + // so we need to flip the vertical coordinate in the hitobject container's space + if (scrollingInfo.Direction.Value == ScrollingDirection.Down) + targetPosition = -hitObject.Position.Y; + else + targetPosition = hitObject.Position.Y; + + hitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition, + editorClock.CurrentTime, + scrollingInfo.TimeRange.Value, + objectParent.DrawHeight); + } + + adjustColumn(dragEvent); + } + + private void adjustColumn(DragEvent dragEvent) + { + var lastColumn = composer.ColumnAt(dragEvent.ScreenSpaceLastMousePosition); + var currentColumn = composer.ColumnAt(dragEvent.ScreenSpaceMousePosition); + if (lastColumn == null || currentColumn == null) + return; + + int columnDelta = currentColumn.Index - lastColumn.Index; + if (columnDelta == 0) + return; + + int minColumn = int.MaxValue; + int maxColumn = int.MinValue; + + foreach (var obj in SelectedHitObjects.OfType()) + { + if (obj.Column < minColumn) + minColumn = obj.Column; + if (obj.Column > maxColumn) + maxColumn = obj.Column; + } + + columnDelta = MathHelper.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); + + foreach (var obj in SelectedHitObjects.OfType()) + obj.Column += columnDelta; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs index e0dd1430fe..fab9c27c6d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/OsuSelectionBlueprint.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; @@ -17,7 +15,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints : base(hitObject) { } - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => OsuObject.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs index aa33d4c89a..32258572bf 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderCircleSelectionBlueprint.cs @@ -1,9 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Framework.Input.Events; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -12,13 +9,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders { public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint { - private readonly Slider slider; - public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position) : base(hitObject) { - this.slider = slider; - InternalChild = new SliderCirclePiece(slider, position); Select(); @@ -26,7 +19,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders // Todo: This is temporary, since the slider circle masks don't do anything special yet. In the future they will handle input. public override bool HandlePositionalInput => false; - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) => slider.Position += dragEvent.Delta; } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs index f8f632535d..eefdc7e214 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerSelectionBlueprint.cs @@ -1,9 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Framework.Input.Events; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -22,10 +19,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos); - - public override void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects) - { - // Spinners don't support position adjustments - } } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index a706e1d4be..0d50f27016 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Osu.Edit { @@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Osu.Edit new SpinnerCompositionTool() }; + public override SelectionBox CreateSelectionBox() => new OsuSelectionBox(); + protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both }; public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs new file mode 100644 index 0000000000..ca7d26e879 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Screens.Edit.Compose.Components; + +namespace osu.Game.Rulesets.Osu.Edit +{ + public class OsuSelectionBox : SelectionBox + { + public override void HandleDrag(DragEvent dragEvent) + { + base.HandleDrag(dragEvent); + + foreach (var h in SelectedHitObjects.OfType()) + { + if (h is Spinner) + { + // Spinners don't support position adjustments + continue; + } + + h.Position += dragEvent.Delta; + } + } + } +} diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index c9d6719a92..c27f0929c6 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using osu.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -135,8 +134,6 @@ namespace osu.Game.Rulesets.Edit return true; } - public abstract void AdjustPosition(DragEvent dragEvent, IEnumerable selectedObjects); - /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 5d334ca559..b2d692bd39 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -12,6 +12,7 @@ using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; using OpenTK; using OpenTK.Input; @@ -24,8 +25,11 @@ namespace osu.Game.Screens.Edit.Compose.Components { public const float BORDER_RADIUS = 2; + protected IEnumerable SelectedBlueprints => selectedBlueprints; private readonly List selectedBlueprints; + protected IEnumerable SelectedHitObjects => selectedBlueprints.Select(b => b.HitObject.HitObject); + private Drawable outline; [Resolved] @@ -59,12 +63,8 @@ namespace osu.Game.Screens.Edit.Compose.Components #region User Input Handling - public void HandleDrag(DragEvent dragEvent) + public virtual void HandleDrag(DragEvent dragEvent) { - // Todo: Various forms of snapping - - foreach (var blueprint in selectedBlueprints) - blueprint.AdjustPosition(dragEvent, selectedBlueprints.Select(b => b.HitObject)); } protected override bool OnKeyDown(KeyDownEvent e) @@ -90,19 +90,19 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Bind an action to deselect all selected blueprints. /// - public Action DeselectAll { private get; set; } + internal Action DeselectAll { private get; set; } /// /// Handle a blueprint becoming selected. /// /// The blueprint. - public void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint); + internal void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint); /// /// Handle a blueprint becoming deselected. /// /// The blueprint. - public void HandleDeselected(SelectionBlueprint blueprint) + internal void HandleDeselected(SelectionBlueprint blueprint) { selectedBlueprints.Remove(blueprint); @@ -115,7 +115,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// Handle a blueprint requesting selection. /// /// The blueprint. - public void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state) + internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state) { if (state.Keyboard.ControlPressed) { From ce956d7fd41feb9ca9e3a3201bad7834756302dd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 16:19:56 +0900 Subject: [PATCH 11/39] Fix exception when order of objects changes --- osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs index 83a04639eb..9dd0d617c4 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs @@ -6,6 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; using OpenTK; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Edit { var hitObject = blueprint.HitObject; - var objectParent = hitObject.Parent; + var objectParent = (HitObjectContainer)hitObject.Parent; // Using the hitobject position is required since AdjustPosition can be invoked multiple times per frame // without the position having been updated by the parenting ScrollingHitObjectContainer @@ -49,10 +50,14 @@ namespace osu.Game.Rulesets.Mania.Edit else targetPosition = hitObject.Position.Y; + objectParent.Remove(hitObject); + hitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition, editorClock.CurrentTime, scrollingInfo.TimeRange.Value, objectParent.DrawHeight); + + objectParent.Add(hitObject); } adjustColumn(dragEvent); From 595e2ffbffba517f949da656d84346884a59f305 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 16:20:21 +0900 Subject: [PATCH 12/39] Unbind event when column changes --- osu.Game.Rulesets.Mania/UI/Column.cs | 9 +++++++++ osu.Game/Rulesets/UI/Playfield.cs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 4c1929f182..45b8ab2b00 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -145,6 +145,15 @@ namespace osu.Game.Rulesets.Mania.UI HitObjectContainer.Add(hitObject); } + public override bool Remove(DrawableHitObject h) + { + if (!base.Remove(h)) + return false; + + h.OnNewResult -= OnNewResult; + return true; + } + internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 886eb3ac0e..76045bb650 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.UI /// Remove a DrawableHitObject from this Playfield. /// /// The DrawableHitObject to remove. - public virtual void Remove(DrawableHitObject h) => HitObjectContainer.Remove(h); + public virtual bool Remove(DrawableHitObject h) => HitObjectContainer.Remove(h); /// /// Registers a as a nested . From 55edeb095d2e276fa14074029081e9ddce04e0b0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 16:58:11 +0900 Subject: [PATCH 13/39] SelectionBox -> SelectionHandler --- .../Edit/ManiaHitObjectComposer.cs | 2 +- ...electionBox.cs => ManiaSelectionHandler.cs} | 2 +- .../Edit/OsuHitObjectComposer.cs | 2 +- ...uSelectionBox.cs => OsuSelectionHandler.cs} | 2 +- .../Visual/TestCaseHitObjectComposer.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 5 ++--- .../Compose/Components/BlueprintContainer.cs | 18 +++++++++--------- .../Screens/Edit/Compose/Components/DragBox.cs | 2 +- .../{SelectionBox.cs => SelectionHandler.cs} | 12 ++++++++---- 9 files changed, 25 insertions(+), 22 deletions(-) rename osu.Game.Rulesets.Mania/Edit/{ManiaSelectionBox.cs => ManiaSelectionHandler.cs} (98%) rename osu.Game.Rulesets.Osu/Edit/{OsuSelectionBox.cs => OsuSelectionHandler.cs} (93%) rename osu.Game/Screens/Edit/Compose/Components/{SelectionBox.cs => SelectionHandler.cs} (91%) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index eca70a03d4..e6eb1c9f0e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania.Edit new NoteCompositionTool() }; - public override SelectionBox CreateSelectionBox() => new ManiaSelectionBox(); + public override SelectionHandler CreateSelectionHandler() => new ManiaSelectionHandler(); public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) { diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs similarity index 98% rename from osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs rename to osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 9dd0d617c4..944e634c9c 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionBox.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -13,7 +13,7 @@ using OpenTK; namespace osu.Game.Rulesets.Mania.Edit { - public class ManiaSelectionBox : SelectionBox + public class ManiaSelectionHandler : SelectionHandler { [Resolved] private IScrollingInfo scrollingInfo { get; set; } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index 0d50f27016..117af9e853 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Edit new SpinnerCompositionTool() }; - public override SelectionBox CreateSelectionBox() => new OsuSelectionBox(); + public override SelectionHandler CreateSelectionHandler() => new OsuSelectionHandler(); protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs similarity index 93% rename from osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs rename to osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index ca7d26e879..54f629cbea 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionBox.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -8,7 +8,7 @@ using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Osu.Edit { - public class OsuSelectionBox : SelectionBox + public class OsuSelectionHandler : SelectionHandler { public override void HandleDrag(DragEvent dragEvent) { diff --git a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs index d894d2738e..d0eb63bf57 100644 --- a/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs +++ b/osu.Game.Tests/Visual/TestCaseHitObjectComposer.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { - typeof(SelectionBox), + typeof(SelectionHandler), typeof(DragBox), typeof(HitObjectComposer), typeof(OsuHitObjectComposer), diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index d41fd5c201..da7c3dda6a 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -171,10 +171,9 @@ namespace osu.Game.Rulesets.Edit public virtual SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) => null; /// - /// Creates a which outlines s - /// and handles hitobject pattern adjustments. + /// Creates a which outlines s and handles movement of selections. /// - public virtual SelectionBox CreateSelectionBox() => new SelectionBox(); + public virtual SelectionHandler CreateSelectionHandler() => new SelectionHandler(); /// /// Creates a which provides a layer above or below the . diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 1623ef0100..4664d521ec 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private Container placementBlueprintContainer; private PlacementBlueprint currentPlacement; - private SelectionBox selectionBox; + private SelectionHandler selectionHandler; private IEnumerable selections => selectionBlueprints.Children.Where(c => c.IsAlive); @@ -37,16 +37,16 @@ namespace osu.Game.Screens.Edit.Compose.Components [BackgroundDependencyLoader] private void load() { - selectionBox = composer.CreateSelectionBox(); - selectionBox.DeselectAll = deselectAll; + selectionHandler = composer.CreateSelectionHandler(); + selectionHandler.DeselectAll = deselectAll; var dragBox = new DragBox(select); - dragBox.DragEnd += () => selectionBox.UpdateVisibility(); + dragBox.DragEnd += () => selectionHandler.UpdateVisibility(); InternalChildren = new[] { dragBox, - selectionBox, + selectionHandler, selectionBlueprints = new SelectionBlueprintContainer { RelativeSizeAxes = Axes.Both }, placementBlueprintContainer = new Container { RelativeSizeAxes = Axes.Both }, dragBox.CreateProxy() @@ -168,19 +168,19 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onBlueprintSelected(SelectionBlueprint blueprint) { - selectionBox.HandleSelected(blueprint); + selectionHandler.HandleSelected(blueprint); selectionBlueprints.ChangeChildDepth(blueprint, 1); } private void onBlueprintDeselected(SelectionBlueprint blueprint) { - selectionBox.HandleDeselected(blueprint); + selectionHandler.HandleDeselected(blueprint); selectionBlueprints.ChangeChildDepth(blueprint, 0); } - private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionBox.HandleSelectionRequested(blueprint, state); + private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); - private void onDragRequested(DragEvent dragEvent) => selectionBox.HandleDrag(dragEvent); + private void onDragRequested(DragEvent dragEvent) => selectionHandler.HandleDrag(dragEvent); private class SelectionBlueprintContainer : Container { diff --git a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs index 1a58f476ac..0e1c9c7304 100644 --- a/osu.Game/Screens/Edit/Compose/Components/DragBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/DragBox.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { Masking = true, BorderColour = Color4.White, - BorderThickness = SelectionBox.BORDER_RADIUS, + BorderThickness = SelectionHandler.BORDER_RADIUS, Child = new Box { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs similarity index 91% rename from osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs rename to osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index b2d692bd39..46c303df35 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -19,9 +19,9 @@ using OpenTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { /// - /// A box which surrounds s and provides interactive handles, context menus etc. + /// A component which outlines s and handles movement of selections. /// - public class SelectionBox : CompositeDrawable + public class SelectionHandler : CompositeDrawable { public const float BORDER_RADIUS = 2; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Edit.Compose.Components [Resolved] private IPlacementHandler placementHandler { get; set; } - public SelectionBox() + public SelectionHandler() { selectedBlueprints = new List(); @@ -63,6 +63,10 @@ namespace osu.Game.Screens.Edit.Compose.Components #region User Input Handling + /// + /// Handles the selected s being dragged. + /// + /// The drag event. public virtual void HandleDrag(DragEvent dragEvent) { } @@ -139,7 +143,7 @@ namespace osu.Game.Screens.Edit.Compose.Components #endregion /// - /// Updates whether this is visible. + /// Updates whether this is visible. /// internal void UpdateVisibility() { From 52309465ebf3c9592bd1bbbd3c9702e6989dc32f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 17:59:52 +0900 Subject: [PATCH 14/39] Apply some simple fixes --- .../Blueprints/ManiaPlacementBlueprint.cs | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index bfa07d0014..76c4f0c74c 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; -using osu.Framework.Threading; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.UI; @@ -13,7 +12,7 @@ using OpenTK; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public class ManiaPlacementBlueprint : PlacementBlueprint + public abstract class ManiaPlacementBlueprint : PlacementBlueprint where T : ManiaHitObject { protected new T HitObject => (T)base.HitObject; @@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints [Resolved] private IScrollingInfo scrollingInfo { get; set; } - public ManiaPlacementBlueprint(T hitObject) + protected ManiaPlacementBlueprint(T hitObject) : base(hitObject) { RelativeSizeAxes = Axes.None; @@ -37,27 +36,17 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected override bool OnMouseMove(MouseMoveEvent e) { - updateSnappedPosition(e); - return true; - } - - private ScheduledDelegate scheduledSnappedPositionUpdate; - - private void updateSnappedPosition(MouseMoveEvent e) - { - scheduledSnappedPositionUpdate?.Cancel(); - scheduledSnappedPositionUpdate = Schedule(() => + Column column = ColumnAt(e.ScreenSpaceMousePosition); + if (column == null) + SnappedMousePosition = e.MousePosition; + else { - Column column = ColumnAt(e.ScreenSpaceMousePosition); - if (column == null) - SnappedMousePosition = e.MousePosition; - else - { - // Snap to the column - var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); - SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); - } - }); + // Snap to the column + var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); + SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); + } + + return true; } protected double TimeAt(Vector2 screenSpacePosition) From d1cbaa9612cf1ccd2b14fa53e1de2a2d04b0a973 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 18:02:01 +0900 Subject: [PATCH 15/39] Use the column width --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 3 +++ .../Edit/Blueprints/NotePlacementBlueprint.cs | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 76c4f0c74c..0f020e0884 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -37,10 +37,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected override bool OnMouseMove(MouseMoveEvent e) { Column column = ColumnAt(e.ScreenSpaceMousePosition); + if (column == null) SnappedMousePosition = e.MousePosition; else { + Width = column.DrawWidth; + // Snap to the column var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index 0a904d962e..8114ee914f 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -17,7 +17,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Origin = Anchor.Centre; AutoSizeAxes = Axes.Y; - Width = 45; InternalChild = new EditNotePiece { RelativeSizeAxes = Axes.X }; } From d9b8d2d15c7bf00a823139481d9581af35e4834e Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Mon, 19 Nov 2018 18:05:21 +0900 Subject: [PATCH 16/39] Trim whitespace --- .../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 0f020e0884..a4675f71b3 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints else { Width = column.DrawWidth; - + // Snap to the column var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); From 8071244d97ba007999f6adfa5309e12215bb81d5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 18:40:16 +0900 Subject: [PATCH 17/39] Make sizing happen per-blueprint --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 12 +++++++++--- .../Edit/Blueprints/NotePlacementBlueprint.cs | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index a4675f71b3..7d9bbc064b 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; using OpenTK; @@ -22,6 +23,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints /// protected Vector2 SnappedMousePosition { get; private set; } + /// + /// The width of the closest column to the current mouse position. + /// + protected float SnappedWidth { get; private set; } + [Resolved] private IManiaHitObjectComposer composer { get; set; } @@ -42,7 +48,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints SnappedMousePosition = e.MousePosition; else { - Width = column.DrawWidth; + SnappedWidth = column.DrawWidth; // Snap to the column var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); @@ -80,10 +86,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints switch (scrollingInfo.Direction.Value) { case ScrollingDirection.Up: - position.Y -= DrawHeight / 2; + position.Y -= NotePiece.NOTE_HEIGHT / 2; break; case ScrollingDirection.Down: - position.Y += DrawHeight / 2; + position.Y += NotePiece.NOTE_HEIGHT / 2; break; } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index 8114ee914f..26279de0d5 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); + Width = SnappedWidth; Position = SnappedMousePosition; } From ad950cfc909ad9afbf7790970caf46804e91bae7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 18:38:06 +0900 Subject: [PATCH 18/39] Implement hold note placement --- .../Blueprints/HoldNotePlacementBlueprint.cs | 87 +++++++++++++++++++ .../Edit/HoldNoteCompositionTool.cs | 19 ++++ .../Edit/ManiaHitObjectComposer.cs | 3 +- 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs new file mode 100644 index 0000000000..0e5a381524 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -0,0 +1,87 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints +{ + public class HoldNotePlacementBlueprint : ManiaPlacementBlueprint + { + private readonly EditNotePiece headPiece; + private readonly EditNotePiece tailPiece; + + private PlacementState state; + + public HoldNotePlacementBlueprint() + : base(new HoldNote()) + { + RelativeSizeAxes = Axes.Both; + + InternalChildren = new[] + { + headPiece = new EditNotePiece { Origin = Anchor.Centre }, + tailPiece = new EditNotePiece { Origin = Anchor.Centre } + }; + } + + protected override void Update() + { + base.Update(); + + switch (state) + { + case PlacementState.Start: + headPiece.Position = SnappedMousePosition; + headPiece.Width = SnappedWidth; + break; + case PlacementState.End: + tailPiece.Position = SnappedMousePosition; + tailPiece.Width = headPiece.Width; + break; + } + } + + protected override bool OnMouseDown(MouseDownEvent e) + { + Column column; + if ((column = ColumnAt(e.ScreenSpaceMousePosition)) == null) + return base.OnMouseDown(e); + + HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); + HitObject.Column = column.Index; + + BeginPlacement(); + + state = PlacementState.End; + + return true; + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + var endTime = TimeAt(e.ScreenSpaceMousePosition); + if (endTime < HitObject.StartTime) + { + var tmp = endTime; + endTime = HitObject.StartTime; + HitObject.StartTime = tmp; + } + + HitObject.Duration = endTime - HitObject.StartTime; + + EndPlacement(); + + return true; + } + + private enum PlacementState + { + Start, + End + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs new file mode 100644 index 0000000000..b1872c200f --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/HoldNoteCompositionTool.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Mania.Edit.Blueprints; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class HoldNoteCompositionTool : HitObjectCompositionTool + { + public HoldNoteCompositionTool() + : base("Hold") + { + } + + public override PlacementBlueprint CreatePlacementBlueprint() => new HoldNotePlacementBlueprint(); + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 07684f9eb8..ca952e914d 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -43,7 +43,8 @@ namespace osu.Game.Rulesets.Mania.Edit protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] { - new NoteCompositionTool() + new NoteCompositionTool(), + new HoldNoteCompositionTool() }; public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) From 2ee56e4a789e12048b3dd1f2902e939b3ce5f531 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 18:59:05 +0900 Subject: [PATCH 19/39] Add a body piece --- .../Blueprints/Components/EditBodyPiece.cs | 18 ++++++++++++++++ .../Blueprints/HoldNotePlacementBlueprint.cs | 21 +++++++++++++------ .../Objects/Drawables/Pieces/BodyPiece.cs | 2 +- 3 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs new file mode 100644 index 0000000000..2695d8a911 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; + +namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components +{ + public class EditBodyPiece : BodyPiece + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AccentColour = colours.Yellow; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 0e5a381524..7d28a0cc1a 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -1,16 +1,19 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.UI; +using OpenTK; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { public class HoldNotePlacementBlueprint : ManiaPlacementBlueprint { + private readonly EditBodyPiece bodyPiece; private readonly EditNotePiece headPiece; private readonly EditNotePiece tailPiece; @@ -21,8 +24,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { RelativeSizeAxes = Axes.Both; - InternalChildren = new[] + InternalChildren = new Drawable[] { + bodyPiece = new EditBodyPiece { Origin = Anchor.TopCentre }, headPiece = new EditNotePiece { Origin = Anchor.Centre }, tailPiece = new EditNotePiece { Origin = Anchor.Centre } }; @@ -35,14 +39,20 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints switch (state) { case PlacementState.Start: - headPiece.Position = SnappedMousePosition; - headPiece.Width = SnappedWidth; + headPiece.Position = tailPiece.Position = SnappedMousePosition; + headPiece.Width = tailPiece.Width = SnappedWidth; break; case PlacementState.End: - tailPiece.Position = SnappedMousePosition; - tailPiece.Width = headPiece.Width; + tailPiece.Position = new Vector2(headPiece.Position.X, SnappedMousePosition.Y); break; } + + var topPosition = new Vector2(headPiece.DrawPosition.X, Math.Min(headPiece.DrawPosition.Y, tailPiece.DrawPosition.Y)); + var bottomPosition = new Vector2(headPiece.DrawPosition.X, Math.Max(headPiece.DrawPosition.Y, tailPiece.DrawPosition.Y)); + + bodyPiece.Position = topPosition; + bodyPiece.Width = headPiece.Width; + bodyPiece.Height = (bottomPosition - topPosition).Y; } protected override bool OnMouseDown(MouseDownEvent e) @@ -74,7 +84,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints HitObject.Duration = endTime - HitObject.StartTime; EndPlacement(); - return true; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 619fe06c73..46779b8c14 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces /// /// Represents length-wise portion of a hold note. /// - internal class BodyPiece : Container, IHasAccentColour + public class BodyPiece : Container, IHasAccentColour { private readonly Container subtractionLayer; From c84f49addf09a4137808079504052f2546b6ca4d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 19:02:59 +0900 Subject: [PATCH 20/39] Add testcase --- .../TestCaseHoldNotePlacementBlueprint.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs new file mode 100644 index 0000000000..ea7433268d --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseHoldNotePlacementBlueprint.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Edit.Blueprints; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Mania.Tests +{ + public class TestCaseHoldNotePlacementBlueprint : ManiaPlacementBlueprintTestCase + { + protected override DrawableHitObject CreateHitObject(HitObject hitObject) => new DrawableHoldNote((HoldNote)hitObject); + protected override PlacementBlueprint CreateBlueprint() => new HoldNotePlacementBlueprint(); + } +} From d5b937f88fba7bb341f0ddba0f4df999880d27c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 19 Nov 2018 19:17:03 +0900 Subject: [PATCH 21/39] Fix post-merge issue --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index b42758ebad..d41fd5c201 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Edit /// /// Whether the user's cursor is currently in an area of the that is valid for placement. /// - public virtual bool CursorInPlacementArea => rulesetContainer.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); + public virtual bool CursorInPlacementArea => RulesetContainer.Playfield.ReceivePositionalInputAt(inputManager.CurrentState.Mouse.Position); /// /// Adds a to the and visualises it. From 4ba3fa4ab6af212df03ff6805632b7a7f9ceb0a8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Nov 2018 10:44:48 +0900 Subject: [PATCH 22/39] osuTK --- .../ManiaPlacementBlueprintTestCase.cs | 4 ++-- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 2 +- osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs | 2 +- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs index 0c87978f15..b5c08d6837 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaPlacementBlueprintTestCase.cs @@ -11,8 +11,8 @@ using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; -using OpenTK; -using OpenTK.Graphics; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 7d9bbc064b..8394328e2c 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI.Scrolling; -using OpenTK; +using osuTK; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { diff --git a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs index 6347370d72..977c7dd525 100644 --- a/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/IManiaHitObjectComposer.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Mania.UI; -using OpenTK; +using osuTK; namespace osu.Game.Rulesets.Mania.Edit { diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 07684f9eb8..6280f93606 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -12,7 +12,7 @@ using osu.Framework.Allocation; using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI; -using OpenTK; +using osuTK; namespace osu.Game.Rulesets.Mania.Edit { diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index e113123454..b7c80c1adc 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -13,7 +13,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; -using OpenTK; +using osuTK; namespace osu.Game.Rulesets.Mania.UI { From 91aa00b0e99df3773f54021995d58ad171650563 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Nov 2018 10:54:54 +0900 Subject: [PATCH 23/39] Add helper method to get column by position --- .../Edit/ManiaHitObjectComposer.cs | 17 ++++++++++++----- .../UI/ManiaRulesetContainer.cs | 8 ++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 6280f93606..8c8fe3b8b9 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -19,26 +19,33 @@ namespace osu.Game.Rulesets.Mania.Edit [Cached(Type = typeof(IManiaHitObjectComposer))] public class ManiaHitObjectComposer : HitObjectComposer, IManiaHitObjectComposer { + protected new ManiaEditRulesetContainer RulesetContainer { get; private set; } + public ManiaHitObjectComposer(Ruleset ruleset) : base(ruleset) { } + /// + /// Retrieves the column that intersects a screen-space position. + /// + /// The screen-space position. + /// The column which intersects with . + public Column ColumnAt(Vector2 screenSpacePosition) => RulesetContainer.GetColumnByPosition(screenSpacePosition); + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - public Column ColumnAt(Vector2 screenSpacePosition) => ((ManiaPlayfield)RulesetContainer.Playfield).GetColumnByPosition(screenSpacePosition); - protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) { - var rulesetContainer = new ManiaEditRulesetContainer(ruleset, beatmap); + RulesetContainer = new ManiaEditRulesetContainer(ruleset, beatmap); // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it - dependencies.CacheAs(rulesetContainer.ScrollingInfo); + dependencies.CacheAs(RulesetContainer.ScrollingInfo); - return rulesetContainer; + return RulesetContainer; } protected override IReadOnlyList CompositionTools => new HitObjectCompositionTool[] diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 321dd4e1cb..5263d4dcb9 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -25,6 +25,7 @@ using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; +using osuTK; namespace osu.Game.Rulesets.Mania.UI { @@ -80,6 +81,13 @@ namespace osu.Game.Rulesets.Mania.UI Config.BindWith(ManiaSetting.ScrollTime, TimeRange); } + /// + /// 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); + protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) { Anchor = Anchor.Centre, From 60ffad169fc1c1984537aff5f4eb5963728254a3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Nov 2018 11:47:48 +0900 Subject: [PATCH 24/39] Fix post-merge errors --- .../ManiaSelectionBlueprintTestCase.cs | 4 ++-- .../Edit/Blueprints/ManiaSelectionBlueprint.cs | 2 +- osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs index f64e54c878..50de5ce7a3 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaSelectionBlueprintTestCase.cs @@ -7,8 +7,8 @@ using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; -using OpenTK; -using OpenTK.Graphics; +using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.Tests { diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index 6752378dfd..fc0180069d 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -42,7 +42,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } - } public override void Show() { @@ -54,5 +53,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { HitObject.AlwaysAlive = false; base.Hide(); + } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 944e634c9c..4cb417a32e 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit.Compose.Components; -using OpenTK; +using osuTK; namespace osu.Game.Rulesets.Mania.Edit { From f9f300b215d07f3859bc32f73f6ad2981e0f1f33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 26 Nov 2018 16:08:56 +0900 Subject: [PATCH 25/39] Fix drag breaking if scrolling while dragging --- .../Blueprints/ManiaSelectionBlueprint.cs | 22 ++++++++++ .../Edit/ManiaSelectionHandler.cs | 43 ++++++++++++++++--- .../Edit/OsuSelectionHandler.cs | 7 +-- osu.Game/Rulesets/Edit/SelectionBlueprint.cs | 4 +- .../Compose/Components/BlueprintContainer.cs | 2 +- .../Compose/Components/SelectionHandler.cs | 4 +- 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index fc0180069d..df229b23ae 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -14,6 +15,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { public class ManiaSelectionBlueprint : SelectionBlueprint { + public Vector2 ScreenSpaceMouseDownPosition { get; private set; } + public Vector2 MouseDownPosition { get; private set; } + protected new DrawableManiaHitObject HitObject => (DrawableManiaHitObject)base.HitObject; protected IClock EditorClock { get; private set; } @@ -43,6 +47,24 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); } + protected override bool OnMouseDown(MouseDownEvent e) + { + ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; + MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + + return base.OnMouseDown(e); + } + + protected override bool OnDrag(DragEvent e) + { + var result = base.OnDrag(e); + + ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; + MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + + return result; + } + public override void Show() { HitObject.AlwaysAlive = true; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 4cb417a32e..1d6b9d6c69 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -5,6 +5,8 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Input.Events; using osu.Framework.Timing; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -29,11 +31,42 @@ namespace osu.Game.Rulesets.Mania.Edit editorClock = clock; } - public override void HandleDrag(DragEvent dragEvent) + public override void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) { - foreach (var blueprint in SelectedBlueprints) + adjustOrigins((ManiaSelectionBlueprint)blueprint); + performDragMovement(dragEvent); + performColumnMovement(dragEvent); + + base.HandleDrag(blueprint, dragEvent); + } + + /// + /// Ensures that the position of hitobjects remains centred to the mouse position. + /// E.g. The hitobject position will change if the editor scrolls while a hitobject is dragged. + /// + /// The that received the drag event. + private void adjustOrigins(ManiaSelectionBlueprint reference) + { + var referenceParent = (HitObjectContainer)reference.HitObject.Parent; + + float offsetFromReferenceOrigin = reference.MouseDownPosition.Y - reference.HitObject.OriginPosition.Y; + float targetPosition = referenceParent.ToLocalSpace(reference.ScreenSpaceMouseDownPosition).Y - offsetFromReferenceOrigin; + + // Flip the vertical coordinate space when scrolling downwards + if (scrollingInfo.Direction.Value == ScrollingDirection.Down) + targetPosition = targetPosition - referenceParent.DrawHeight; + + float movementDelta = targetPosition - reference.HitObject.Position.Y; + + foreach (var b in SelectedBlueprints.OfType()) + b.HitObject.Y += movementDelta; + } + + private void performDragMovement(DragEvent dragEvent) + { + foreach (var b in SelectedBlueprints) { - var hitObject = blueprint.HitObject; + var hitObject = b.HitObject; var objectParent = (HitObjectContainer)hitObject.Parent; @@ -59,11 +92,9 @@ namespace osu.Game.Rulesets.Mania.Edit objectParent.Add(hitObject); } - - adjustColumn(dragEvent); } - private void adjustColumn(DragEvent dragEvent) + private void performColumnMovement(DragEvent dragEvent) { var lastColumn = composer.ColumnAt(dragEvent.ScreenSpaceLastMousePosition); var currentColumn = composer.ColumnAt(dragEvent.ScreenSpaceMousePosition); diff --git a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs index 54f629cbea..0c7e571ef5 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuSelectionHandler.cs @@ -3,6 +3,7 @@ using System.Linq; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Edit.Compose.Components; @@ -10,10 +11,8 @@ namespace osu.Game.Rulesets.Osu.Edit { public class OsuSelectionHandler : SelectionHandler { - public override void HandleDrag(DragEvent dragEvent) + public override void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) { - base.HandleDrag(dragEvent); - foreach (var h in SelectedHitObjects.OfType()) { if (h is Spinner) @@ -24,6 +23,8 @@ namespace osu.Game.Rulesets.Osu.Edit h.Position += dragEvent.Delta; } + + base.HandleDrag(blueprint, dragEvent); } } } diff --git a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs index 04e8834946..ec4df01e55 100644 --- a/osu.Game/Rulesets/Edit/SelectionBlueprint.cs +++ b/osu.Game/Rulesets/Edit/SelectionBlueprint.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Edit /// /// Invoked when this has requested drag. /// - public event Action DragRequested; + public event Action DragRequested; /// /// The which this applies to. @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Edit protected override bool OnDrag(DragEvent e) { - DragRequested?.Invoke(e); + DragRequested?.Invoke(this, e); return true; } diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 4664d521ec..80bfe21367 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -180,7 +180,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onSelectionRequested(SelectionBlueprint blueprint, InputState state) => selectionHandler.HandleSelectionRequested(blueprint, state); - private void onDragRequested(DragEvent dragEvent) => selectionHandler.HandleDrag(dragEvent); + private void onDragRequested(SelectionBlueprint blueprint, DragEvent dragEvent) => selectionHandler.HandleDrag(blueprint, dragEvent); private class SelectionBlueprintContainer : Container { diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs index 0140f3aa75..f8ceeedba9 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionHandler.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osuTK; using osuTK.Input; @@ -66,8 +67,9 @@ namespace osu.Game.Screens.Edit.Compose.Components /// /// Handles the selected s being dragged. /// + /// The that received the drag event. /// The drag event. - public virtual void HandleDrag(DragEvent dragEvent) + public virtual void HandleDrag(SelectionBlueprint blueprint, DragEvent dragEvent) { } From f42d4a9382eb600d66d8492c27d82b417844554a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 28 Nov 2018 19:02:23 +0900 Subject: [PATCH 26/39] Add wildcard scope to oauth requests --- osu.Game/Online/API/OAuth.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index 7892df9aab..f60567a706 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -178,6 +178,7 @@ namespace osu.Game.Online.API AddParameter("grant_type", GrantType); AddParameter("client_id", ClientId); AddParameter("client_secret", ClientSecret); + AddParameter("scope", "*"); base.PrePerform(); } From 52bc47499fc03683edb9fc07adea6fc8eeb7cbed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 12:11:45 +0900 Subject: [PATCH 27/39] Fix spinners not having proper lifetimes --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d0d9479ed1..8e809306a4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -217,6 +217,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { + case ArmedState.Idle: + Expire(true); + break; case ArmedState.Hit: sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out); break; From aea84f737bdd5f898862ab73c6166b710abe163e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 29 Nov 2018 12:12:29 +0900 Subject: [PATCH 28/39] Fix taiko hitobjects potentially disappearing before being judged --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 2 -- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 1081f185ad..2ac46a14f2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -16,8 +16,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Clock?.CurrentTime >= HitObject.StartTime - HitObject.TimePreempt; - private readonly ShakeContainer shakeContainer; protected DrawableOsuHitObject(OsuHitObject hitObject) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 5490e75c14..8718269eed 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -84,6 +84,8 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; + public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart; + public readonly Bindable State = new Bindable(); protected DrawableHitObject(HitObject hitObject) From 8fd04cb47bd9260e52e6280e31aeab43d385408b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Nov 2018 13:20:37 +0900 Subject: [PATCH 29/39] Fix mania placement blueprints appearing outside valid stage placement area --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 41c80dfb68..32d8ef343f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using System; using System.Collections.Generic; +using System.Linq; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Drawables; @@ -17,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.UI { private readonly List stages = new List(); + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos)); + public ManiaPlayfield(List stageDefinitions) { if (stageDefinitions == null) From 3d46ac7d35393061778a89aae794bb9c3e43cee3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Nov 2018 13:21:11 +0900 Subject: [PATCH 30/39] Remove unnecessary high frequency input --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 2414a682e9..7f39bdc4f9 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -7,7 +7,6 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Edit /// /// A blueprint which governs the creation of a new to actualisation. /// - public abstract class PlacementBlueprint : CompositeDrawable, IStateful, IRequireHighFrequencyMousePosition + public abstract class PlacementBlueprint : CompositeDrawable, IStateful { /// /// Invoked when has changed. From d1c976880c976ef19aa7d18dcb3c3a73e684e315 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Nov 2018 14:15:23 +0900 Subject: [PATCH 31/39] Fix incorrect margin/spacing handling --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 14 +++++--------- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 8 ++++++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 8394328e2c..c36c32bb84 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -44,17 +44,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { Column column = ColumnAt(e.ScreenSpaceMousePosition); - if (column == null) - SnappedMousePosition = e.MousePosition; - else - { - SnappedWidth = column.DrawWidth; + if (column == null) return false; - // Snap to the column - var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); - SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); - } + SnappedWidth = column.DrawWidth; + // Snap to the column + var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); + SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); return true; } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 68030cdfb2..58e2066f72 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -183,6 +183,6 @@ namespace osu.Game.Rulesets.Mania.UI public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) // This probably shouldn't exist as is, but the columns in the stage are separated by a 1px border - => DrawRectangle.Inflate(new Vector2(1, 0)).Contains(ToLocalSpace(screenSpacePos)); + => DrawRectangle.Inflate(new Vector2(ManiaStage.COLUMN_SPACING / 2, 0)).Contains(ToLocalSpace(screenSpacePos)); } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 58a49a7877..ab835cbbb3 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.UI /// public class ManiaStage : ScrollingPlayfield { + public const float COLUMN_SPACING = 1; + public const float HIT_TARGET_POSITION = 50; public IReadOnlyList Columns => columnFlow.Children; @@ -40,6 +42,8 @@ namespace osu.Game.Rulesets.Mania.UI private List normalColumnColours = new List(); private Color4 specialColumnColour; + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Columns.Any(c => c.ReceivePositionalInputAt(screenSpacePos)); + private readonly int firstColumnIndex; public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) @@ -84,8 +88,8 @@ namespace osu.Game.Rulesets.Mania.UI RelativeSizeAxes = Axes.Y, AutoSizeAxes = Axes.X, Direction = FillDirection.Horizontal, - Padding = new MarginPadding { Left = 1, Right = 1 }, - Spacing = new Vector2(1, 0) + Padding = new MarginPadding { Left = COLUMN_SPACING, Right = COLUMN_SPACING }, + Spacing = new Vector2(COLUMN_SPACING, 0) }, } }, From 7ffc597a8e8426e3e03266e333c42712f27c1eb9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Nov 2018 14:55:20 +0900 Subject: [PATCH 32/39] Fix one-frame issues --- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 7f39bdc4f9..1d568313ca 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -49,6 +49,10 @@ namespace osu.Game.Rulesets.Edit RelativeSizeAxes = Axes.Both; + // This is required to allow the blueprint's position to be updated via OnMouseMove/Handle + // on the same frame it is made visible via a PlacementState change. + AlwaysPresent = true; + Alpha = 0; } From ab0ce463624ebf52bb44f261d014af667ef95da3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Nov 2018 18:13:15 +0900 Subject: [PATCH 33/39] Make hold note placement blueprints look a bit more blueprint-y --- .../Blueprints/Components/EditBodyPiece.cs | 3 +++ .../Objects/Drawables/Pieces/BodyPiece.cs | 20 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs index 2695d8a911..41b2e950f9 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/Components/EditBodyPiece.cs @@ -13,6 +13,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components private void load(OsuColour colours) { AccentColour = colours.Yellow; + + Background.Alpha = 0.5f; + Foreground.Alpha = 0; } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 6aafe3ff81..8dbf33c183 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -19,8 +19,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces { private readonly Container subtractionLayer; - private readonly Drawable background; - private readonly BufferedContainer foreground; + protected readonly Drawable Background; + protected readonly BufferedContainer Foreground; private readonly BufferedContainer subtractionContainer; public BodyPiece() @@ -29,8 +29,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces Children = new[] { - background = new Box { RelativeSizeAxes = Axes.Both }, - foreground = new BufferedContainer + Background = new Box { RelativeSizeAxes = Axes.Both }, + Foreground = new BufferedContainer { Blending = BlendingMode.Additive, RelativeSizeAxes = Axes.Both, @@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces Radius = DrawWidth }; - foreground.ForceRedraw(); + Foreground.ForceRedraw(); subtractionContainer.ForceRedraw(); subtractionCache.Validate(); @@ -137,18 +137,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces if (!IsLoaded) return; - foreground.Colour = AccentColour.Opacity(0.5f); - background.Colour = AccentColour.Opacity(0.7f); + Foreground.Colour = AccentColour.Opacity(0.5f); + Background.Colour = AccentColour.Opacity(0.7f); const float animation_length = 50; - foreground.ClearTransforms(false, nameof(foreground.Colour)); + Foreground.ClearTransforms(false, nameof(Foreground.Colour)); if (hitting) { // wait for the next sync point double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2); - using (foreground.BeginDelayedSequence(synchronisedOffset)) - foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(foreground.Colour, animation_length).Loop(); + using (Foreground.BeginDelayedSequence(synchronisedOffset)) + Foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(Foreground.Colour, animation_length).Loop(); } subtractionCache.Invalidate(); From 085acf29a0ab3b9750d19981683a2df1e30eac48 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 29 Nov 2018 19:29:36 +0900 Subject: [PATCH 34/39] Fix blueprints behaving incorrectly --- .../Blueprints/HoldNotePlacementBlueprint.cs | 60 ++++++----------- .../Blueprints/ManiaPlacementBlueprint.cs | 67 +++++++++++++------ .../Edit/Blueprints/NotePlacementBlueprint.cs | 16 ----- 3 files changed, 64 insertions(+), 79 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs index 481c141b9f..081bdffc27 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNotePlacementBlueprint.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; using osuTK; namespace osu.Game.Rulesets.Mania.Edit.Blueprints @@ -17,8 +16,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints private readonly EditNotePiece headPiece; private readonly EditNotePiece tailPiece; - private PlacementState state; - public HoldNotePlacementBlueprint() : base(new HoldNote()) { @@ -36,15 +33,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { base.Update(); - switch (state) + if (Column != null) { - case PlacementState.Start: - headPiece.Position = tailPiece.Position = SnappedMousePosition; - headPiece.Width = tailPiece.Width = SnappedWidth; - break; - case PlacementState.End: - tailPiece.Position = new Vector2(headPiece.Position.X, SnappedMousePosition.Y); - break; + headPiece.Y = PositionAt(HitObject.StartTime); + tailPiece.Y = PositionAt(HitObject.EndTime); } var topPosition = new Vector2(headPiece.DrawPosition.X, Math.Min(headPiece.DrawPosition.Y, tailPiece.DrawPosition.Y)); @@ -55,42 +47,28 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints bodyPiece.Height = (bottomPosition - topPosition).Y; } - protected override bool OnMouseDown(MouseDownEvent e) + private double originalStartTime; + + protected override bool OnMouseMove(MouseMoveEvent e) { - Column column; - if ((column = ColumnAt(e.ScreenSpaceMousePosition)) == null) - return base.OnMouseDown(e); + base.OnMouseMove(e); - HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); - HitObject.Column = column.Index; - - BeginPlacement(); - - state = PlacementState.End; - - return true; - } - - protected override bool OnMouseUp(MouseUpEvent e) - { - var endTime = TimeAt(e.ScreenSpaceMousePosition); - if (endTime < HitObject.StartTime) + if (PlacementBegun) { - var tmp = endTime; - endTime = HitObject.StartTime; - HitObject.StartTime = tmp; + var endTime = TimeAt(e.ScreenSpaceMousePosition); + + HitObject.StartTime = endTime < originalStartTime ? endTime : originalStartTime; + HitObject.Duration = Math.Abs(endTime - originalStartTime); + } + else + { + headPiece.Width = tailPiece.Width = SnappedWidth; + headPiece.X = tailPiece.X = SnappedMousePosition.X; + + originalStartTime = HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); } - HitObject.Duration = endTime - HitObject.StartTime; - - EndPlacement(); return true; } - - private enum PlacementState - { - Start, - End - } } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index c36c32bb84..d76d20f2b8 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects; @@ -13,11 +14,14 @@ using osuTK; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { - public abstract class ManiaPlacementBlueprint : PlacementBlueprint + public abstract class ManiaPlacementBlueprint : PlacementBlueprint, + IRequireHighFrequencyMousePosition // the playfield could be moving behind us where T : ManiaHitObject { protected new T HitObject => (T)base.HitObject; + protected Column Column; + /// /// The current mouse position, snapped to the closest column. /// @@ -40,31 +44,49 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints RelativeSizeAxes = Axes.None; } + protected override bool OnMouseDown(MouseDownEvent e) + { + if (Column == null) + return base.OnMouseDown(e); + + HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); + HitObject.Column = Column.Index; + + BeginPlacement(); + return true; + } + + protected override bool OnMouseUp(MouseUpEvent e) + { + EndPlacement(); + return base.OnMouseUp(e); + } + protected override bool OnMouseMove(MouseMoveEvent e) { - Column column = ColumnAt(e.ScreenSpaceMousePosition); + if (!PlacementBegun) + Column = ColumnAt(e.ScreenSpaceMousePosition); - if (column == null) return false; + if (Column == null) return false; - SnappedWidth = column.DrawWidth; + SnappedWidth = Column.DrawWidth; // Snap to the column - var parentPos = Parent.ToLocalSpace(column.ToScreenSpace(new Vector2(column.DrawWidth / 2, 0))); + var parentPos = Parent.ToLocalSpace(Column.ToScreenSpace(new Vector2(Column.DrawWidth / 2, 0))); SnappedMousePosition = new Vector2(parentPos.X, e.MousePosition.Y); return true; } protected double TimeAt(Vector2 screenSpacePosition) { - var column = ColumnAt(screenSpacePosition); - if (column == null) + if (Column == null) return 0; - var hitObjectContainer = column.HitObjectContainer; + var hitObjectContainer = Column.HitObjectContainer; // If we're scrolling downwards, a position of 0 is actually further away from the hit target // so we need to flip the vertical coordinate in the hitobject container's space - var hitObjectPos = column.HitObjectContainer.ToLocalSpace(applyPositionOffset(screenSpacePosition)).Y; + var hitObjectPos = Column.HitObjectContainer.ToLocalSpace(applyPositionOffset(screenSpacePosition, false)).Y; if (scrollingInfo.Direction.Value == ScrollingDirection.Down) hitObjectPos = hitObjectContainer.DrawHeight - hitObjectPos; @@ -74,21 +96,22 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints hitObjectContainer.DrawHeight); } - protected Column ColumnAt(Vector2 screenSpacePosition) - => composer.ColumnAt(applyPositionOffset(screenSpacePosition)); - - private Vector2 applyPositionOffset(Vector2 position) + protected float PositionAt(double time) { - switch (scrollingInfo.Direction.Value) - { - case ScrollingDirection.Up: - position.Y -= NotePiece.NOTE_HEIGHT / 2; - break; - case ScrollingDirection.Down: - position.Y += NotePiece.NOTE_HEIGHT / 2; - break; - } + var pos = scrollingInfo.Algorithm.PositionAt(time, + EditorClock.CurrentTime, + scrollingInfo.TimeRange.Value, + Column.HitObjectContainer.DrawHeight); + return applyPositionOffset(Column.HitObjectContainer.ToSpaceOfOtherDrawable(new Vector2(0, pos), Parent), true).Y; + } + + protected Column ColumnAt(Vector2 screenSpacePosition) + => composer.ColumnAt(applyPositionOffset(screenSpacePosition, false)); + + private Vector2 applyPositionOffset(Vector2 position, bool reverse) + { + position.Y += (scrollingInfo.Direction.Value == ScrollingDirection.Up && !reverse ? -1 : 1) * NotePiece.NOTE_HEIGHT / 2; return position; } } diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs index 26279de0d5..acb43e38ba 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/NotePlacementBlueprint.cs @@ -2,10 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Framework.Input.Events; using osu.Game.Rulesets.Mania.Edit.Blueprints.Components; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Edit.Blueprints { @@ -28,19 +26,5 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints Width = SnappedWidth; Position = SnappedMousePosition; } - - protected override bool OnClick(ClickEvent e) - { - Column column; - if ((column = ColumnAt(e.ScreenSpaceMousePosition)) == null) - return base.OnClick(e); - - HitObject.StartTime = TimeAt(e.ScreenSpaceMousePosition); - HitObject.Column = column.Index; - - EndPlacement(); - - return true; - } } } From a1666fb7fa2deea4b9a81f940440b5db1d209f1c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:21:20 +0900 Subject: [PATCH 35/39] MouseDownPosition -> DragPosition --- .../Edit/Blueprints/ManiaSelectionBlueprint.cs | 12 ++++++------ .../Edit/ManiaSelectionHandler.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs index df229b23ae..f190843f5d 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaSelectionBlueprint.cs @@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { public class ManiaSelectionBlueprint : SelectionBlueprint { - public Vector2 ScreenSpaceMouseDownPosition { get; private set; } - public Vector2 MouseDownPosition { get; private set; } + public Vector2 ScreenSpaceDragPosition { get; private set; } + public Vector2 DragPosition { get; private set; } protected new DrawableManiaHitObject HitObject => (DrawableManiaHitObject)base.HitObject; @@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected override bool OnMouseDown(MouseDownEvent e) { - ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; - MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + ScreenSpaceDragPosition = e.ScreenSpaceMousePosition; + DragPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); return base.OnMouseDown(e); } @@ -59,8 +59,8 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints { var result = base.OnDrag(e); - ScreenSpaceMouseDownPosition = e.ScreenSpaceMousePosition; - MouseDownPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); + ScreenSpaceDragPosition = e.ScreenSpaceMousePosition; + DragPosition = HitObject.ToLocalSpace(e.ScreenSpaceMousePosition); return result; } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs index 1d6b9d6c69..828f6d87bc 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaSelectionHandler.cs @@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit { var referenceParent = (HitObjectContainer)reference.HitObject.Parent; - float offsetFromReferenceOrigin = reference.MouseDownPosition.Y - reference.HitObject.OriginPosition.Y; - float targetPosition = referenceParent.ToLocalSpace(reference.ScreenSpaceMouseDownPosition).Y - offsetFromReferenceOrigin; + float offsetFromReferenceOrigin = reference.DragPosition.Y - reference.HitObject.OriginPosition.Y; + float targetPosition = referenceParent.ToLocalSpace(reference.ScreenSpaceDragPosition).Y - offsetFromReferenceOrigin; // Flip the vertical coordinate space when scrolling downwards if (scrollingInfo.Direction.Value == ScrollingDirection.Down) From 7543af07dd71a3a029fe5b7decb769925edc812d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:30:50 +0900 Subject: [PATCH 36/39] Remove weird reference --- osu.Game/osu.Game.csproj | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 55132038ff..a1578b6eb8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,9 +24,4 @@ - - - ..\osu.Game.Rulesets.Osu.Tests\bin\Debug\netcoreapp2.1\osu.Game.dll - - - \ No newline at end of file + From 0ee5a5bdb4404850493c06d520c904ecb8bf9ca3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:57:25 +0900 Subject: [PATCH 37/39] Add support for keyboard seeking in the editor --- osu.Game/Screens/Edit/Editor.cs | 66 +++++++++++++++++++--------- osu.Game/Screens/Edit/EditorClock.cs | 12 +++-- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c4fb9dc419..6d81897552 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -20,6 +20,7 @@ using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Compose; using osu.Game.Screens.Edit.Design; +using osuTK.Input; namespace osu.Game.Screens.Edit { @@ -157,29 +158,19 @@ namespace osu.Game.Screens.Edit bottomBackground.Colour = colours.Gray2; } - private void exportBeatmap() + protected override bool OnKeyDown(KeyDownEvent e) { - host.OpenFileExternally(Beatmap.Value.Save()); - } - - private void onModeChanged(EditorScreenMode mode) - { - currentScreen?.Exit(); - - switch (mode) + switch (e.Key) { - case EditorScreenMode.Compose: - currentScreen = new ComposeScreen(); - break; - case EditorScreenMode.Design: - currentScreen = new DesignScreen(); - break; - default: - currentScreen = new EditorScreen(); - break; + case Key.Left: + seek(-1); + return true; + case Key.Right: + seek(1); + return true; } - LoadComponentAsync(currentScreen, screenContainer.Add); + return base.OnKeyDown(e); } private double scrollAccumulation; @@ -193,9 +184,9 @@ namespace osu.Game.Screens.Edit while (Math.Abs(scrollAccumulation) > precision) { if (scrollAccumulation > 0) - clock.SeekBackward(!clock.IsRunning); + seek(-1); else - clock.SeekForward(!clock.IsRunning); + seek(1); scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision); } @@ -224,7 +215,40 @@ namespace osu.Game.Screens.Edit Beatmap.Value.Track.Tempo.Value = 1; Beatmap.Value.Track.Start(); } + return base.OnExiting(next); } + + private void exportBeatmap() => host.OpenFileExternally(Beatmap.Value.Save()); + + private void onModeChanged(EditorScreenMode mode) + { + currentScreen?.Exit(); + + switch (mode) + { + case EditorScreenMode.Compose: + currentScreen = new ComposeScreen(); + break; + case EditorScreenMode.Design: + currentScreen = new DesignScreen(); + break; + default: + currentScreen = new EditorScreen(); + break; + } + + LoadComponentAsync(currentScreen, screenContainer.Add); + } + + private void seek(int direction) + { + double amount = GetContainingInputManager().CurrentState.Keyboard.ShiftPressed ? 2 : 1; + + if (direction < 1) + clock.SeekBackward(!clock.IsRunning, amount); + else + clock.SeekForward(!clock.IsRunning, amount); + } } } diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 465e3a43e2..aa30b1a9f5 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -68,16 +68,20 @@ namespace osu.Game.Screens.Edit /// Seeks backwards by one beat length. /// /// Whether to snap to the closest beat after seeking. - public void SeekBackward(bool snapped = false) => seek(-1, snapped); + /// The relative amount (magnitude) which should be seeked. + public void SeekBackward(bool snapped = false, double amount = 1) => seek(-1, snapped, amount); /// /// Seeks forwards by one beat length. /// /// Whether to snap to the closest beat after seeking. - public void SeekForward(bool snapped = false) => seek(1, snapped); + /// The relative amount (magnitude) which should be seeked. + public void SeekForward(bool snapped = false, double amount = 1) => seek(1, snapped, amount); - private void seek(int direction, bool snapped) + private void seek(int direction, bool snapped, double amount = 1) { + if (amount <= 0) throw new ArgumentException("Value should be greater than zero", nameof(amount)); + var timingPoint = ControlPointInfo.TimingPointAt(CurrentTime); if (direction < 0 && timingPoint.Time == CurrentTime) { @@ -87,7 +91,7 @@ namespace osu.Game.Screens.Edit timingPoint = ControlPointInfo.TimingPoints[--activeIndex]; } - double seekAmount = timingPoint.BeatLength / beatDivisor; + double seekAmount = timingPoint.BeatLength / beatDivisor * amount; double seekTime = CurrentTime + seekAmount * direction; if (!snapped || ControlPointInfo.TimingPoints.Count == 0) From ab621bd87348738f416b5f162134d2c717d693b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 30 Nov 2018 14:41:17 +0900 Subject: [PATCH 38/39] Toggle pause in editor with spacebar --- osu.Game/Screens/Edit/Components/PlaybackControl.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 7d68f32495..d2e51d1f57 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -13,6 +13,7 @@ using osu.Framework.Timing; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using osuTK.Input; namespace osu.Game.Screens.Edit.Components { @@ -63,6 +64,18 @@ namespace osu.Game.Screens.Edit.Components tabs.Current.ValueChanged += newValue => Beatmap.Value.Track.Tempo.Value = newValue; } + protected override bool OnKeyDown(KeyDownEvent e) + { + switch (e.Key) + { + case Key.Space: + togglePause(); + return true; + } + + return base.OnKeyDown(e); + } + private void togglePause() { if (adjustableClock.IsRunning) From bc3fcb87b752aab58263a65d4c08b7930c070035 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 30 Nov 2018 15:47:55 +0900 Subject: [PATCH 39/39] Use input events rather than scene graph traversals --- osu.Game/Screens/Edit/Editor.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 6d81897552..9bccefc508 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -163,10 +163,10 @@ namespace osu.Game.Screens.Edit switch (e.Key) { case Key.Left: - seek(-1); + seek(e, -1); return true; case Key.Right: - seek(1); + seek(e, 1); return true; } @@ -184,9 +184,9 @@ namespace osu.Game.Screens.Edit while (Math.Abs(scrollAccumulation) > precision) { if (scrollAccumulation > 0) - seek(-1); + seek(e, -1); else - seek(1); + seek(e, 1); scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision); } @@ -241,9 +241,9 @@ namespace osu.Game.Screens.Edit LoadComponentAsync(currentScreen, screenContainer.Add); } - private void seek(int direction) + private void seek(UIEvent e, int direction) { - double amount = GetContainingInputManager().CurrentState.Keyboard.ShiftPressed ? 2 : 1; + double amount = e.ShiftPressed ? 2 : 1; if (direction < 1) clock.SeekBackward(!clock.IsRunning, amount);