// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Linq; using osu.Framework.Allocation; 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; using osu.Game.Screens.Edit.Compose.Components; namespace osu.Game.Rulesets.Mania.Edit { public class ManiaSelectionHandler : SelectionHandler { [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 bool HandleMovement(MoveSelectionEvent moveEvent) { var maniaBlueprint = (ManiaSelectionBlueprint)moveEvent.Blueprint; int lastColumn = maniaBlueprint.DrawableObject.HitObject.Column; performDragMovement(moveEvent); performColumnMovement(lastColumn, moveEvent); return true; } private void performDragMovement(MoveSelectionEvent moveEvent) { float delta = moveEvent.InstantDelta.Y; foreach (var selectionBlueprint in SelectedBlueprints) { var b = (OverlaySelectionBlueprint)selectionBlueprint; var hitObject = b.DrawableObject; var objectParent = (HitObjectContainer)hitObject.Parent; // We receive multiple movement events per frame such that we can't rely on updating the start time // since the scrolling hitobject container requires at least one update frame to update the position. // However the position needs to be valid for future movement events to calculate the correct deltas. hitObject.Y += delta; } } private void performColumnMovement(int lastColumn, MoveSelectionEvent moveEvent) { var currentColumn = composer.ColumnAt(moveEvent.ScreenSpacePosition); if (currentColumn == null) return; int columnDelta = currentColumn.Index - lastColumn; 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 = Math.Clamp(columnDelta, -minColumn, composer.TotalColumns - 1 - maxColumn); foreach (var obj in SelectedHitObjects.OfType()) obj.Column += columnDelta; } } }