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 @@ protected override void Update() 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.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 @@ protected override RulesetContainer CreateRulesetContainer(Rules 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 @@ public OsuSelectionBlueprint(DrawableHitObject hitObject) : 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 @@ public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider sli // 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 @@ public SpinnerSelectionBlueprint(DrawableSpinner spinner) } 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.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 @@ protected override RulesetContainer CreateRulesetContainer(Ruleset 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 @@ protected override bool OnDrag(DragEvent e) 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.States; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Objects; using OpenTK; using OpenTK.Input; @@ -24,8 +25,11 @@ public class SelectionBox : CompositeDrawable { 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 @@ private void load(OsuColour colours) #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 @@ protected override bool OnKeyDown(KeyDownEvent e) /// /// 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 @@ public void HandleDeselected(SelectionBlueprint blueprint) /// 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) {