1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-15 12:47:18 +08:00

Merge pull request #10432 from peppy/editor-reverse-pattern

Add "reverse pattern" support to editor selection handler
This commit is contained in:
Dan Balasescu 2020-10-09 19:19:24 +09:00 committed by GitHub
commit 62690e4873
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 4 deletions

View File

@ -7,6 +7,7 @@ using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Utils;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit.Compose.Components;
@ -25,6 +26,7 @@ namespace osu.Game.Rulesets.Osu.Edit
SelectionBox.CanRotate = canOperate;
SelectionBox.CanScaleX = canOperate;
SelectionBox.CanScaleY = canOperate;
SelectionBox.CanReverse = canOperate;
}
protected override void OnOperationEnded()
@ -41,6 +43,54 @@ namespace osu.Game.Rulesets.Osu.Edit
/// </summary>
private Vector2? referenceOrigin;
public override bool HandleReverse()
{
var hitObjects = selectedMovableObjects;
double endTime = hitObjects.Max(h => h.GetEndTime());
double startTime = hitObjects.Min(h => h.StartTime);
bool moreThanOneObject = hitObjects.Length > 1;
foreach (var h in hitObjects)
{
if (moreThanOneObject)
h.StartTime = endTime - (h.GetEndTime() - startTime);
if (h is Slider slider)
{
var points = slider.Path.ControlPoints.ToArray();
Vector2 endPos = points.Last().Position.Value;
slider.Path.ControlPoints.Clear();
slider.Position += endPos;
PathType? lastType = null;
for (var i = 0; i < points.Length; i++)
{
var p = points[i];
p.Position.Value -= endPos;
// propagate types forwards to last null type
if (i == points.Length - 1)
p.Type.Value = lastType;
else if (p.Type.Value != null)
{
var newType = p.Type.Value;
p.Type.Value = lastType;
lastType = newType;
}
slider.Path.ControlPoints.Insert(0, p);
}
}
}
return true;
}
public override bool HandleFlip(Direction direction)
{
var hitObjects = selectedMovableObjects;

View File

@ -57,6 +57,7 @@ namespace osu.Game.Rulesets.Objects
c.Changed += invalidate;
break;
case NotifyCollectionChangedAction.Reset:
case NotifyCollectionChangedAction.Remove:
foreach (var c in args.OldItems.Cast<PathControlPoint>())
c.Changed -= invalidate;

View File

@ -17,10 +17,28 @@ namespace osu.Game.Screens.Edit.Compose.Components
public Action<float> OnRotation;
public Action<Vector2, Anchor> OnScale;
public Action<Direction> OnFlip;
public Action OnReverse;
public Action OperationStarted;
public Action OperationEnded;
private bool canReverse;
/// <summary>
/// Whether pattern reversing support should be enabled.
/// </summary>
public bool CanReverse
{
get => canReverse;
set
{
if (canReverse == value) return;
canReverse = value;
recreate();
}
}
private bool canRotate;
/// <summary>
@ -125,6 +143,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (CanScaleX && CanScaleY) addFullScaleComponents();
if (CanScaleY) addYScaleComponents();
if (CanRotate) addRotationComponents();
if (CanReverse) addButton(FontAwesome.Solid.Backward, "Reverse pattern", () => OnReverse?.Invoke());
}
private void addRotationComponents()

View File

@ -103,6 +103,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
OnRotation = angle => HandleRotation(angle),
OnScale = (amount, anchor) => HandleScale(amount, anchor),
OnFlip = direction => HandleFlip(direction),
OnReverse = () => HandleReverse(),
};
/// <summary>
@ -141,7 +142,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// Handles the selected <see cref="DrawableHitObject"/>s being rotated.
/// </summary>
/// <param name="angle">The delta angle to apply to the selection.</param>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be moved.</returns>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be rotated.</returns>
public virtual bool HandleRotation(float angle) => false;
/// <summary>
@ -149,16 +150,22 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// </summary>
/// <param name="scale">The delta scale to apply, in playfield local coordinates.</param>
/// <param name="anchor">The point of reference where the scale is originating from.</param>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be moved.</returns>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be scaled.</returns>
public virtual bool HandleScale(Vector2 scale, Anchor anchor) => false;
/// <summary>
/// Handled the selected <see cref="DrawableHitObject"/>s being flipped.
/// Handles the selected <see cref="DrawableHitObject"/>s being flipped.
/// </summary>
/// <param name="direction">The direction to flip</param>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be moved.</returns>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be flipped.</returns>
public virtual bool HandleFlip(Direction direction) => false;
/// <summary>
/// Handles the selected <see cref="DrawableHitObject"/>s being reversed pattern-wise.
/// </summary>
/// <returns>Whether any <see cref="DrawableHitObject"/>s could be reversed.</returns>
public virtual bool HandleReverse() => false;
public bool OnPressed(PlatformAction action)
{
switch (action.ActionMethod)