mirror of
https://github.com/ppy/osu.git
synced 2026-05-24 04:09:53 +08:00
Merge pull request #31917 from bdach/nudge-fix
Fix nudge operations incurring FP error from coordinate space conversions
This commit is contained in:
@@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
@@ -12,6 +13,7 @@ using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
using Direction = osu.Framework.Graphics.Direction;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Edit
|
||||
@@ -38,6 +40,13 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
return true;
|
||||
}
|
||||
|
||||
moveSelection(deltaX);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void moveSelection(float deltaX)
|
||||
{
|
||||
EditorBeatmap.PerformOnSelection(h =>
|
||||
{
|
||||
if (!(h is CatchHitObject catchObject)) return;
|
||||
@@ -48,7 +57,60 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
foreach (var nested in catchObject.NestedHitObjects.OfType<CatchHitObject>())
|
||||
nested.OriginalX += deltaX;
|
||||
});
|
||||
}
|
||||
|
||||
private bool nudgeMovementActive;
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
// Until the keys below are global actions, this will prevent conflicts with "seek between sample points"
|
||||
// which has a default of ctrl+shift+arrows.
|
||||
if (e.ShiftPressed)
|
||||
return false;
|
||||
|
||||
if (e.ControlPressed)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Left:
|
||||
return nudgeSelection(-1);
|
||||
|
||||
case Key.Right:
|
||||
return nudgeSelection(1);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyUpEvent e)
|
||||
{
|
||||
base.OnKeyUp(e);
|
||||
|
||||
if (nudgeMovementActive && !e.ControlPressed)
|
||||
{
|
||||
EditorBeatmap.EndChange();
|
||||
nudgeMovementActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the current selection spatially by the specified delta, in gamefield coordinates (ie. the same coordinates as the blueprints).
|
||||
/// </summary>
|
||||
private bool nudgeSelection(float deltaX)
|
||||
{
|
||||
if (!nudgeMovementActive)
|
||||
{
|
||||
nudgeMovementActive = true;
|
||||
EditorBeatmap.BeginChange();
|
||||
}
|
||||
|
||||
var firstBlueprint = SelectedBlueprints.FirstOrDefault();
|
||||
|
||||
if (firstBlueprint == null)
|
||||
return false;
|
||||
|
||||
moveSelection(deltaX);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
SelectionBox.CanReverse = EditorBeatmap.SelectedHitObjects.Count > 1 || EditorBeatmap.SelectedHitObjects.Any(s => s is Slider);
|
||||
}
|
||||
|
||||
private bool nudgeMovementActive;
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
if (e.Key == Key.M && e.ControlPressed && e.ShiftPressed)
|
||||
@@ -48,9 +50,43 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
return true;
|
||||
}
|
||||
|
||||
// Until the keys below are global actions, this will prevent conflicts with "seek between sample points"
|
||||
// which has a default of ctrl+shift+arrows.
|
||||
if (e.ShiftPressed)
|
||||
return false;
|
||||
|
||||
if (e.ControlPressed)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Left:
|
||||
return nudgeSelection(new Vector2(-1, 0));
|
||||
|
||||
case Key.Right:
|
||||
return nudgeSelection(new Vector2(1, 0));
|
||||
|
||||
case Key.Up:
|
||||
return nudgeSelection(new Vector2(0, -1));
|
||||
|
||||
case Key.Down:
|
||||
return nudgeSelection(new Vector2(0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyUpEvent e)
|
||||
{
|
||||
base.OnKeyUp(e);
|
||||
|
||||
if (nudgeMovementActive && !e.ControlPressed)
|
||||
{
|
||||
EditorBeatmap.EndChange();
|
||||
nudgeMovementActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HandleMovement(MoveSelectionEvent<HitObject> moveEvent)
|
||||
{
|
||||
var hitObjects = selectedMovableObjects;
|
||||
@@ -70,6 +106,13 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
if (hitObjects.Any(h => Precision.AlmostEquals(localDelta, -h.StackOffset)))
|
||||
return true;
|
||||
|
||||
moveObjects(hitObjects, localDelta);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void moveObjects(OsuHitObject[] hitObjects, Vector2 localDelta)
|
||||
{
|
||||
// this will potentially move the selection out of bounds...
|
||||
foreach (var h in hitObjects)
|
||||
h.Position += localDelta;
|
||||
@@ -81,7 +124,26 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
// this intentionally bypasses the editor `UpdateState()` / beatmap processor flow for performance reasons,
|
||||
// as the entire flow is too expensive to run on every movement.
|
||||
Scheduler.AddOnce(OsuBeatmapProcessor.ApplyStacking, EditorBeatmap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the current selection spatially by the specified delta, in gamefield coordinates (ie. the same coordinates as the blueprints).
|
||||
/// </summary>
|
||||
/// <param name="delta"></param>
|
||||
private bool nudgeSelection(Vector2 delta)
|
||||
{
|
||||
if (!nudgeMovementActive)
|
||||
{
|
||||
nudgeMovementActive = true;
|
||||
EditorBeatmap.BeginChange();
|
||||
}
|
||||
|
||||
var firstBlueprint = SelectedBlueprints.FirstOrDefault();
|
||||
|
||||
if (firstBlueprint == null)
|
||||
return false;
|
||||
|
||||
moveObjects(selectedMovableObjects, delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Edit.Components.TernaryButtons;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Compose.Components
|
||||
{
|
||||
@@ -112,71 +111,6 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
blueprint.DrawableObject = drawableObject;
|
||||
}
|
||||
|
||||
private bool nudgeMovementActive;
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
// Until the keys below are global actions, this will prevent conflicts with "seek between sample points"
|
||||
// which has a default of ctrl+shift+arrows.
|
||||
if (e.ShiftPressed)
|
||||
return false;
|
||||
|
||||
if (e.ControlPressed)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Left:
|
||||
return nudgeSelection(new Vector2(-1, 0));
|
||||
|
||||
case Key.Right:
|
||||
return nudgeSelection(new Vector2(1, 0));
|
||||
|
||||
case Key.Up:
|
||||
return nudgeSelection(new Vector2(0, -1));
|
||||
|
||||
case Key.Down:
|
||||
return nudgeSelection(new Vector2(0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyUpEvent e)
|
||||
{
|
||||
base.OnKeyUp(e);
|
||||
|
||||
if (nudgeMovementActive && !e.ControlPressed)
|
||||
{
|
||||
Beatmap.EndChange();
|
||||
nudgeMovementActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the current selection spatially by the specified delta, in gamefield coordinates (ie. the same coordinates as the blueprints).
|
||||
/// </summary>
|
||||
/// <param name="delta"></param>
|
||||
private bool nudgeSelection(Vector2 delta)
|
||||
{
|
||||
if (!nudgeMovementActive)
|
||||
{
|
||||
nudgeMovementActive = true;
|
||||
Beatmap.BeginChange();
|
||||
}
|
||||
|
||||
var firstBlueprint = SelectionHandler.SelectedBlueprints.FirstOrDefault();
|
||||
|
||||
if (firstBlueprint == null)
|
||||
return false;
|
||||
|
||||
// convert to game space coordinates
|
||||
delta = firstBlueprint.ToScreenSpace(delta) - firstBlueprint.ToScreenSpace(Vector2.Zero);
|
||||
|
||||
SelectionHandler.HandleMovement(new MoveSelectionEvent<HitObject>(firstBlueprint, delta));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updatePlacementNewCombo()
|
||||
{
|
||||
if (CurrentHitObjectPlacement?.HitObject is IHasComboInformation c)
|
||||
|
||||
Reference in New Issue
Block a user