1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 17:52:56 +08:00

Merge branch 'master' into editor-toolbox-expand

This commit is contained in:
Bartłomiej Dach 2022-01-06 19:01:02 +01:00 committed by GitHub
commit f5742d3d2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 32 deletions

View File

@ -52,16 +52,25 @@ namespace osu.Game.Rulesets.Catch.Edit
return true; return true;
} }
public override bool HandleFlip(Direction direction) public override bool HandleFlip(Direction direction, bool flipOverOrigin)
{ {
if (SelectedItems.Count == 0)
return false;
// This could be implemented in the future if there's a requirement for it.
if (direction == Direction.Vertical)
return false;
var selectionRange = CatchHitObjectUtils.GetPositionRange(SelectedItems); var selectionRange = CatchHitObjectUtils.GetPositionRange(SelectedItems);
bool changed = false; bool changed = false;
EditorBeatmap.PerformOnSelection(h => EditorBeatmap.PerformOnSelection(h =>
{ {
if (h is CatchHitObject catchObject) if (h is CatchHitObject catchObject)
changed |= handleFlip(selectionRange, catchObject); changed |= handleFlip(selectionRange, catchObject, flipOverOrigin);
}); });
return changed; return changed;
} }
@ -116,7 +125,7 @@ namespace osu.Game.Rulesets.Catch.Edit
return Math.Clamp(deltaX, lowerBound, upperBound); return Math.Clamp(deltaX, lowerBound, upperBound);
} }
private bool handleFlip(PositionRange selectionRange, CatchHitObject hitObject) private bool handleFlip(PositionRange selectionRange, CatchHitObject hitObject, bool flipOverOrigin)
{ {
switch (hitObject) switch (hitObject)
{ {
@ -124,7 +133,7 @@ namespace osu.Game.Rulesets.Catch.Edit
return false; return false;
case JuiceStream juiceStream: case JuiceStream juiceStream:
juiceStream.OriginalX = selectionRange.GetFlippedPosition(juiceStream.OriginalX); juiceStream.OriginalX = getFlippedPosition(juiceStream.OriginalX);
foreach (var point in juiceStream.Path.ControlPoints) foreach (var point in juiceStream.Path.ControlPoints)
point.Position *= new Vector2(-1, 1); point.Position *= new Vector2(-1, 1);
@ -133,9 +142,11 @@ namespace osu.Game.Rulesets.Catch.Edit
return true; return true;
default: default:
hitObject.OriginalX = selectionRange.GetFlippedPosition(hitObject.OriginalX); hitObject.OriginalX = getFlippedPosition(hitObject.OriginalX);
return true; return true;
} }
float getFlippedPosition(float original) => flipOverOrigin ? CatchPlayfield.WIDTH - original : selectionRange.GetFlippedPosition(original);
} }
} }
} }

View File

@ -10,6 +10,7 @@ using osu.Game.Extensions;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components;
using osuTK; using osuTK;
@ -84,18 +85,28 @@ namespace osu.Game.Rulesets.Osu.Edit
return true; return true;
} }
public override bool HandleFlip(Direction direction) public override bool HandleFlip(Direction direction, bool flipOverOrigin)
{ {
var hitObjects = selectedMovableObjects; var hitObjects = selectedMovableObjects;
var selectedObjectsQuad = getSurroundingQuad(hitObjects); var flipQuad = flipOverOrigin ? new Quad(0, 0, OsuPlayfield.BASE_SIZE.X, OsuPlayfield.BASE_SIZE.Y) : getSurroundingQuad(hitObjects);
bool didFlip = false;
foreach (var h in hitObjects) foreach (var h in hitObjects)
{ {
h.Position = GetFlippedPosition(direction, selectedObjectsQuad, h.Position); var flippedPosition = GetFlippedPosition(direction, flipQuad, h.Position);
if (!Precision.AlmostEquals(flippedPosition, h.Position))
{
h.Position = flippedPosition;
didFlip = true;
}
if (h is Slider slider) if (h is Slider slider)
{ {
didFlip = true;
foreach (var point in slider.Path.ControlPoints) foreach (var point in slider.Path.ControlPoints)
{ {
point.Position = new Vector2( point.Position = new Vector2(
@ -106,7 +117,7 @@ namespace osu.Game.Rulesets.Osu.Edit
} }
} }
return true; return didFlip;
} }
public override bool HandleScale(Vector2 scale, Anchor reference) public override bool HandleScale(Vector2 scale, Anchor reference)

View File

@ -77,6 +77,8 @@ namespace osu.Game.Input.Bindings
new KeyBinding(new[] { InputKey.K }, GlobalAction.EditorNudgeRight), new KeyBinding(new[] { InputKey.K }, GlobalAction.EditorNudgeRight),
new KeyBinding(new[] { InputKey.G }, GlobalAction.EditorCycleGridDisplayMode), new KeyBinding(new[] { InputKey.G }, GlobalAction.EditorCycleGridDisplayMode),
new KeyBinding(new[] { InputKey.F5 }, GlobalAction.EditorTestGameplay), new KeyBinding(new[] { InputKey.F5 }, GlobalAction.EditorTestGameplay),
new KeyBinding(new[] { InputKey.Control, InputKey.H }, GlobalAction.EditorFlipHorizontally),
new KeyBinding(new[] { InputKey.Control, InputKey.J }, GlobalAction.EditorFlipVertically),
}; };
public IEnumerable<KeyBinding> InGameKeyBindings => new[] public IEnumerable<KeyBinding> InGameKeyBindings => new[]
@ -292,6 +294,12 @@ namespace osu.Game.Input.Bindings
EditorCycleGridDisplayMode, EditorCycleGridDisplayMode,
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorTestGameplay))] [LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorTestGameplay))]
EditorTestGameplay EditorTestGameplay,
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorFlipHorizontally))]
EditorFlipHorizontally,
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorFlipVertically))]
EditorFlipVertically,
} }
} }

View File

@ -229,6 +229,16 @@ namespace osu.Game.Localisation
/// </summary> /// </summary>
public static LocalisableString EditorNudgeRight => new TranslatableString(getKey(@"editor_nudge_right"), @"Nudge selection right"); public static LocalisableString EditorNudgeRight => new TranslatableString(getKey(@"editor_nudge_right"), @"Nudge selection right");
/// <summary>
/// "Flip selection horizontally"
/// </summary>
public static LocalisableString EditorFlipHorizontally => new TranslatableString(getKey(@"editor_flip_horizontally"), @"Flip selection horizontally");
/// <summary>
/// "Flip selection vertically"
/// </summary>
public static LocalisableString EditorFlipVertically => new TranslatableString(getKey(@"editor_flip_vertically"), @"Flip selection vertically");
/// <summary> /// <summary>
/// "Toggle skin editor" /// "Toggle skin editor"
/// </summary> /// </summary>

View File

@ -21,7 +21,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
public Func<float, bool> OnRotation; public Func<float, bool> OnRotation;
public Func<Vector2, Anchor, bool> OnScale; public Func<Vector2, Anchor, bool> OnScale;
public Func<Direction, bool> OnFlip; public Func<Direction, bool, bool> OnFlip;
public Func<bool> OnReverse; public Func<bool> OnReverse;
public Action OperationStarted; public Action OperationStarted;
@ -174,12 +174,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
{ {
case Key.G: case Key.G:
return CanReverse && runOperationFromHotkey(OnReverse); return CanReverse && runOperationFromHotkey(OnReverse);
case Key.H:
return CanFlipX && runOperationFromHotkey(() => OnFlip?.Invoke(Direction.Horizontal) ?? false);
case Key.J:
return CanFlipY && runOperationFromHotkey(() => OnFlip?.Invoke(Direction.Vertical) ?? false);
} }
return base.OnKeyDown(e); return base.OnKeyDown(e);
@ -287,12 +281,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
private void addXFlipComponents() private void addXFlipComponents()
{ {
addButton(FontAwesome.Solid.ArrowsAltH, "Flip horizontally (Ctrl-H)", () => OnFlip?.Invoke(Direction.Horizontal)); addButton(FontAwesome.Solid.ArrowsAltH, "Flip horizontally", () => OnFlip?.Invoke(Direction.Horizontal, false));
} }
private void addYFlipComponents() private void addYFlipComponents()
{ {
addButton(FontAwesome.Solid.ArrowsAltV, "Flip vertically (Ctrl-J)", () => OnFlip?.Invoke(Direction.Vertical)); addButton(FontAwesome.Solid.ArrowsAltV, "Flip vertically", () => OnFlip?.Invoke(Direction.Vertical, false));
} }
private void addButton(IconUsage icon, string tooltip, Action action) private void addButton(IconUsage icon, string tooltip, Action action)

View File

@ -17,6 +17,7 @@ using osu.Framework.Input.Events;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osuTK; using osuTK;
using osuTK.Input; using osuTK.Input;
@ -26,7 +27,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// <summary> /// <summary>
/// A component which outlines items and handles movement of selections. /// A component which outlines items and handles movement of selections.
/// </summary> /// </summary>
public abstract class SelectionHandler<T> : CompositeDrawable, IKeyBindingHandler<PlatformAction>, IHasContextMenu public abstract class SelectionHandler<T> : CompositeDrawable, IKeyBindingHandler<PlatformAction>, IKeyBindingHandler<GlobalAction>, IHasContextMenu
{ {
/// <summary> /// <summary>
/// The currently selected blueprints. /// The currently selected blueprints.
@ -127,9 +128,10 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// <summary> /// <summary>
/// Handles the selected items being flipped. /// Handles the selected items being flipped.
/// </summary> /// </summary>
/// <param name="direction">The direction to flip</param> /// <param name="direction">The direction to flip.</param>
/// <param name="flipOverOrigin">Whether the flip operation should be global to the playfield's origin or local to the selected pattern.</param>
/// <returns>Whether any items could be flipped.</returns> /// <returns>Whether any items could be flipped.</returns>
public virtual bool HandleFlip(Direction direction) => false; public virtual bool HandleFlip(Direction direction, bool flipOverOrigin) => false;
/// <summary> /// <summary>
/// Handles the selected items being reversed pattern-wise. /// Handles the selected items being reversed pattern-wise.
@ -137,6 +139,27 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// <returns>Whether any items could be reversed.</returns> /// <returns>Whether any items could be reversed.</returns>
public virtual bool HandleReverse() => false; public virtual bool HandleReverse() => false;
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{
if (e.Repeat)
return false;
switch (e.Action)
{
case GlobalAction.EditorFlipHorizontally:
return HandleFlip(Direction.Horizontal, true);
case GlobalAction.EditorFlipVertically:
return HandleFlip(Direction.Vertical, true);
}
return false;
}
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
{
}
public bool OnPressed(KeyBindingPressEvent<PlatformAction> e) public bool OnPressed(KeyBindingPressEvent<PlatformAction> e)
{ {
switch (e.Action) switch (e.Action)

View File

@ -7,7 +7,6 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
@ -17,7 +16,7 @@ using osuTK.Input;
namespace osu.Game.Screens.Edit.Compose.Components.Timeline namespace osu.Game.Screens.Edit.Compose.Components.Timeline
{ {
internal class TimelineSelectionHandler : EditorSelectionHandler, IKeyBindingHandler<GlobalAction> internal class TimelineSelectionHandler : EditorSelectionHandler
{ {
[Resolved] [Resolved]
private Timeline timeline { get; set; } private Timeline timeline { get; set; }
@ -27,7 +26,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
// for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation // for now we always allow movement. snapping is provided by the Timeline's "distance" snap implementation
public override bool HandleMovement(MoveSelectionEvent<HitObject> moveEvent) => true; public override bool HandleMovement(MoveSelectionEvent<HitObject> moveEvent) => true;
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e) public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
{ {
switch (e.Action) switch (e.Action)
{ {
@ -40,11 +39,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
return true; return true;
} }
return false; return base.OnPressed(e);
}
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
{
} }
/// <summary> /// <summary>

View File

@ -126,7 +126,7 @@ namespace osu.Game.Skinning.Editor
return true; return true;
} }
public override bool HandleFlip(Direction direction) public override bool HandleFlip(Direction direction, bool flipOverOrigin)
{ {
var selectionQuad = getSelectionQuad(); var selectionQuad = getSelectionQuad();
Vector2 scaleFactor = direction == Direction.Horizontal ? new Vector2(-1, 1) : new Vector2(1, -1); Vector2 scaleFactor = direction == Direction.Horizontal ? new Vector2(-1, 1) : new Vector2(1, -1);
@ -135,7 +135,7 @@ namespace osu.Game.Skinning.Editor
{ {
var drawableItem = (Drawable)b.Item; var drawableItem = (Drawable)b.Item;
var flippedPosition = GetFlippedPosition(direction, selectionQuad, b.ScreenSpaceSelectionPoint); var flippedPosition = GetFlippedPosition(direction, flipOverOrigin ? drawableItem.Parent.ScreenSpaceDrawQuad : selectionQuad, b.ScreenSpaceSelectionPoint);
updateDrawablePosition(drawableItem, flippedPosition); updateDrawablePosition(drawableItem, flippedPosition);