Merge pull request #23156 from Micha-ohne-el/editor-selection-rotation-snapping

Add rotation snapping to editor selection
This commit is contained in:
Dean Herbert 2023-04-11 00:45:44 +09:00 committed by GitHub
commit 8757276c37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 16 deletions

View File

@ -99,6 +99,16 @@ public static class EditorStrings
/// </summary>
public static LocalisableString TimelineTicks => new TranslatableString(getKey(@"timeline_ticks"), @"Ticks");
/// <summary>
/// "{0:0.0}&#176;"
/// </summary>
public static LocalisableString RotationUnsnapped(float newRotation) => new TranslatableString(getKey(@"rotation_unsnapped"), @"{0:0.0}°", newRotation);
/// <summary>
/// "{0:0.0}&#176; (snapped)"
/// </summary>
public static LocalisableString RotationSnapped(float newRotation) => new TranslatableString(getKey(@"rotation_snapped"), @"{0:0.0}° (snapped)", newRotation);
private static string getKey(string key) => $@"{prefix}:{key}";
}
}

View File

@ -7,14 +7,15 @@
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.EnumExtensions;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osuTK;
using osuTK.Graphics;
using Key = osuTK.Input.Key;
namespace osu.Game.Screens.Edit.Compose.Components
{
@ -26,6 +27,8 @@ public partial class SelectionBoxRotationHandle : SelectionBoxDragHandle, IHasTo
private SpriteIcon icon;
private const float snap_step = 15;
private readonly Bindable<float?> cumulativeRotation = new Bindable<float?>();
[Resolved]
@ -50,18 +53,14 @@ private void load()
});
}
protected override void LoadComplete()
{
base.LoadComplete();
cumulativeRotation.BindValueChanged(_ => updateTooltipText(), true);
}
protected override void UpdateHoverState()
{
base.UpdateHoverState();
icon.FadeColour(!IsHeld && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint);
}
private float rawCumulativeRotation;
protected override bool OnDragStart(DragStartEvent e)
{
bool handle = base.OnDragStart(e);
@ -74,21 +73,36 @@ protected override void OnDrag(DragEvent e)
{
base.OnDrag(e);
float instantaneousAngle = convertDragEventToAngleOfRotation(e);
cumulativeRotation.Value += instantaneousAngle;
rawCumulativeRotation += convertDragEventToAngleOfRotation(e);
if (cumulativeRotation.Value < -180)
cumulativeRotation.Value += 360;
else if (cumulativeRotation.Value > 180)
cumulativeRotation.Value -= 360;
applyRotation(shouldSnap: e.ShiftPressed);
}
HandleRotate?.Invoke(instantaneousAngle);
protected override bool OnKeyDown(KeyDownEvent e)
{
if (IsDragged && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight))
{
applyRotation(shouldSnap: true);
return true;
}
return base.OnKeyDown(e);
}
protected override void OnKeyUp(KeyUpEvent e)
{
base.OnKeyUp(e);
if (IsDragged && (e.Key == Key.ShiftLeft || e.Key == Key.ShiftRight))
applyRotation(shouldSnap: false);
}
protected override void OnDragEnd(DragEndEvent e)
{
base.OnDragEnd(e);
cumulativeRotation.Value = null;
rawCumulativeRotation = 0;
TooltipText = default;
}
private float convertDragEventToAngleOfRotation(DragEvent e)
@ -100,9 +114,19 @@ private float convertDragEventToAngleOfRotation(DragEvent e)
return (endAngle - startAngle) * 180 / MathF.PI;
}
private void updateTooltipText()
private void applyRotation(bool shouldSnap)
{
TooltipText = cumulativeRotation.Value?.ToLocalisableString("0.0°") ?? default;
float oldRotation = cumulativeRotation.Value ?? 0;
float newRotation = shouldSnap ? snap(rawCumulativeRotation, snap_step) : rawCumulativeRotation;
newRotation = (newRotation - 180) % 360 + 180;
cumulativeRotation.Value = newRotation;
HandleRotate?.Invoke(newRotation - oldRotation);
TooltipText = shouldSnap ? EditorStrings.RotationSnapped(newRotation) : EditorStrings.RotationUnsnapped(newRotation);
}
private float snap(float value, float step) => MathF.Round(value / step) * step;
}
}