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>.
// 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<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.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<ManiaHitObject> CreateRulesetContainer(Rules
new NoteCompositionTool()
};
public override SelectionBox CreateSelectionBox() => new ManiaSelectionBox();
public override SelectionBlueprint CreateBlueprintFor(DrawableHitObject 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>.
// 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<DrawableHitObject> selectedObjects) => OsuObject.Position += dragEvent.Delta;
}
}

View File

@ -1,9 +1,6 @@
// 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.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<DrawableHitObject> selectedObjects) => slider.Position += dragEvent.Delta;
}
}

View File

@ -1,9 +1,6 @@
// 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.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<DrawableHitObject> selectedObjects)
{
// Spinners don't support position adjustments
}
}
}

View File

@ -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<OsuHitObject> 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)

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
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<DrawableHitObject> selectedObjects);
/// <summary>
/// The screen-space point that causes this <see cref="SelectionBlueprint"/> to be selected.
/// </summary>

View File

@ -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<SelectionBlueprint> SelectedBlueprints => selectedBlueprints;
private readonly List<SelectionBlueprint> selectedBlueprints;
protected IEnumerable<HitObject> 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)
/// <summary>
/// Bind an action to deselect all selected blueprints.
/// </summary>
public Action DeselectAll { private get; set; }
internal Action DeselectAll { private get; set; }
/// <summary>
/// Handle a blueprint becoming selected.
/// </summary>
/// <param name="blueprint">The blueprint.</param>
public void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint);
internal void HandleSelected(SelectionBlueprint blueprint) => selectedBlueprints.Add(blueprint);
/// <summary>
/// Handle a blueprint becoming deselected.
/// </summary>
/// <param name="blueprint">The blueprint.</param>
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.
/// </summary>
/// <param name="blueprint">The blueprint.</param>
public void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
internal void HandleSelectionRequested(SelectionBlueprint blueprint, InputState state)
{
if (state.Keyboard.ControlPressed)
{