1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 08:53:20 +08:00

Move positional adjustment to SelectionBox

This commit is contained in:
smoogipoo 2018-11-16 17:12:24 +09:00
parent f7fc2ca569
commit 4cbda97b1e
10 changed files with 133 additions and 92 deletions

View File

@ -1,16 +1,10 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input.Events;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Rulesets.Edit; 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.Objects.Drawables;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
using OpenTK; using OpenTK;
@ -45,58 +39,5 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero)); Position = Parent.ToLocalSpace(HitObject.ToScreenSpace(Vector2.Zero));
} }
public override void AdjustPosition(DragEvent dragEvent, IEnumerable<DrawableHitObject> 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<DrawableManiaHitObject>())
{
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);
} }
} }

View File

@ -12,6 +12,7 @@ using osu.Framework.Allocation;
using osu.Game.Rulesets.Mania.Edit.Blueprints; using osu.Game.Rulesets.Mania.Edit.Blueprints;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Compose.Components;
using OpenTK; using OpenTK;
namespace osu.Game.Rulesets.Mania.Edit namespace osu.Game.Rulesets.Mania.Edit
@ -48,6 +49,8 @@ namespace osu.Game.Rulesets.Mania.Edit
new NoteCompositionTool() new NoteCompositionTool()
}; };
public override SelectionBox CreateSelectionBox() => new ManiaSelectionBox();
public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)
{ {
switch (hitObject) switch (hitObject)

View File

@ -0,0 +1,89 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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<ManiaHitObject>())
{
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<ManiaHitObject>())
obj.Column += columnDelta;
}
}
}

View File

@ -1,8 +1,6 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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.Edit;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
@ -17,7 +15,5 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
: base(hitObject) : base(hitObject)
{ {
} }
public override void AdjustPosition(DragEvent dragEvent, IEnumerable<DrawableHitObject> selectedObjects) => OsuObject.Position += dragEvent.Delta;
} }
} }

View File

@ -1,9 +1,6 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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.Edit.Blueprints.Sliders.Components;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
@ -12,13 +9,9 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
{ {
public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint public class SliderCircleSelectionBlueprint : OsuSelectionBlueprint
{ {
private readonly Slider slider;
public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position) public SliderCircleSelectionBlueprint(DrawableOsuHitObject hitObject, Slider slider, SliderPosition position)
: base(hitObject) : base(hitObject)
{ {
this.slider = slider;
InternalChild = new SliderCirclePiece(slider, position); InternalChild = new SliderCirclePiece(slider, position);
Select(); 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. // 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 bool HandlePositionalInput => false;
public override void AdjustPosition(DragEvent dragEvent, IEnumerable<DrawableHitObject> selectedObjects) => slider.Position += dragEvent.Delta;
} }
} }

View File

@ -1,9 +1,6 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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.Edit.Blueprints.Spinners.Components;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; 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 bool ReceivePositionalInputAt(Vector2 screenSpacePos) => piece.ReceivePositionalInputAt(screenSpacePos);
public override void AdjustPosition(DragEvent dragEvent, IEnumerable<DrawableHitObject> selectedObjects)
{
// Spinners don't support position adjustments
}
} }
} }

View File

@ -15,6 +15,7 @@ using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit.Compose.Components;
namespace osu.Game.Rulesets.Osu.Edit namespace osu.Game.Rulesets.Osu.Edit
{ {
@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Osu.Edit
new SpinnerCompositionTool() new SpinnerCompositionTool()
}; };
public override SelectionBox CreateSelectionBox() => new OsuSelectionBox();
protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both }; protected override Container CreateLayerContainer() => new PlayfieldAdjustmentContainer { RelativeSizeAxes = Axes.Both };
public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject) public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject hitObject)

View File

@ -0,0 +1,29 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// 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<OsuHitObject>())
{
if (h is Spinner)
{
// Spinners don't support position adjustments
continue;
}
h.Position += dragEvent.Delta;
}
}
}
}

View File

@ -2,7 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Collections.Generic;
using osu.Framework; using osu.Framework;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -135,8 +134,6 @@ namespace osu.Game.Rulesets.Edit
return true; return true;
} }
public abstract void AdjustPosition(DragEvent dragEvent, IEnumerable<DrawableHitObject> selectedObjects);
/// <summary> /// <summary>
/// The screen-space point that causes this <see cref="SelectionBlueprint"/> to be selected. /// The screen-space point that causes this <see cref="SelectionBlueprint"/> to be selected.
/// </summary> /// </summary>

View File

@ -12,6 +12,7 @@ using osu.Framework.Input.Events;
using osu.Framework.Input.States; using osu.Framework.Input.States;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using OpenTK; using OpenTK;
using OpenTK.Input; using OpenTK.Input;
@ -24,8 +25,11 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
public const float BORDER_RADIUS = 2; public const float BORDER_RADIUS = 2;
protected IEnumerable<SelectionBlueprint> SelectedBlueprints => selectedBlueprints;
private readonly List<SelectionBlueprint> selectedBlueprints; private readonly List<SelectionBlueprint> selectedBlueprints;
protected IEnumerable<HitObject> SelectedHitObjects => selectedBlueprints.Select(b => b.HitObject.HitObject);
private Drawable outline; private Drawable outline;
[Resolved] [Resolved]
@ -59,12 +63,8 @@ namespace osu.Game.Screens.Edit.Compose.Components
#region User Input Handling #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) protected override bool OnKeyDown(KeyDownEvent e)
@ -90,19 +90,19 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// <summary> /// <summary>
/// Bind an action to deselect all selected blueprints. /// Bind an action to deselect all selected blueprints.
/// </summary> /// </summary>
public Action DeselectAll { private get; set; } internal Action DeselectAll { private get; set; }
/// <summary> /// <summary>
/// Handle a blueprint becoming selected. /// Handle a blueprint becoming selected.
/// </summary> /// </summary>
/// <param name="blueprint">The blueprint.</param> /// <param name="blueprint">The blueprint.</param>
public void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint); internal void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint);
/// <summary> /// <summary>
/// Handle a blueprint becoming deselected. /// Handle a blueprint becoming deselected.
/// </summary> /// </summary>
/// <param name="blueprint">The blueprint.</param> /// <param name="blueprint">The blueprint.</param>
public void HandleDeselected(SelectionBlueprint blueprint) internal void HandleDeselected(SelectionBlueprint blueprint)
{ {
selectedBlueprints.Remove(blueprint); selectedBlueprints.Remove(blueprint);
@ -115,7 +115,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// Handle a blueprint requesting selection. /// Handle a blueprint requesting selection.
/// </summary> /// </summary>
/// <param name="blueprint">The blueprint.</param> /// <param name="blueprint">The blueprint.</param>
public void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state) internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
{ {
if (state.Keyboard.ControlPressed) if (state.Keyboard.ControlPressed)
{ {