From 24d377fddb18f60bb72c3da0aca6ae449ffccb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 Jan 2022 17:19:52 +0100 Subject: [PATCH 1/2] Move implementation of drag handle operations to concrete classes --- .../Edit/Compose/Components/SelectionBox.cs | 5 +++-- .../Components/SelectionBoxDragHandle.cs | 8 ------- .../Components/SelectionBoxRotationHandle.cs | 22 +++++++++++++++++++ .../Components/SelectionBoxScaleHandle.cs | 11 ++++++++++ 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 3a31f6ea8c..cda986c7cd 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -15,6 +15,7 @@ using osuTK.Input; namespace osu.Game.Screens.Edit.Compose.Components { + [Cached] public class SelectionBox : CompositeDrawable { public const float BORDER_RADIUS = 3; @@ -306,7 +307,7 @@ namespace osu.Game.Screens.Edit.Compose.Components var handle = new SelectionBoxScaleHandle { Anchor = anchor, - HandleDrag = e => OnScale?.Invoke(e.Delta, anchor) + HandleScale = (delta, a) => OnScale?.Invoke(delta, a) }; handle.OperationStarted += operationStarted; @@ -319,7 +320,7 @@ namespace osu.Game.Screens.Edit.Compose.Components var handle = new SelectionBoxRotationHandle { Anchor = anchor, - HandleDrag = e => OnRotation?.Invoke(convertDragEventToAngleOfRotation(e)) + HandleRotate = angle => OnRotation?.Invoke(angle) }; handle.OperationStarted += operationStarted; diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs index cac907ca5e..c37fefeed4 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxDragHandle.cs @@ -8,20 +8,12 @@ namespace osu.Game.Screens.Edit.Compose.Components { public abstract class SelectionBoxDragHandle : SelectionBoxControl { - public Action HandleDrag { get; set; } - protected override bool OnDragStart(DragStartEvent e) { TriggerOperationStarted(); return true; } - protected override void OnDrag(DragEvent e) - { - HandleDrag?.Invoke(e); - base.OnDrag(e); - } - protected override void OnDragEnd(DragEndEvent e) { TriggerOperationEnded(); diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 65a54292ab..0db36d8902 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; using osu.Framework.Extensions.EnumExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osuTK; using osuTK.Graphics; @@ -12,8 +14,13 @@ namespace osu.Game.Screens.Edit.Compose.Components { public class SelectionBoxRotationHandle : SelectionBoxDragHandle { + public Action HandleRotate { get; set; } + private SpriteIcon icon; + [Resolved] + private SelectionBox selectionBox { get; set; } + [BackgroundDependencyLoader] private void load() { @@ -38,5 +45,20 @@ namespace osu.Game.Screens.Edit.Compose.Components base.UpdateHoverState(); icon.FadeColour(!IsHeld && IsHovered ? Color4.White : Color4.Black, TRANSFORM_DURATION, Easing.OutQuint); } + + protected override void OnDrag(DragEvent e) + { + base.OnDrag(e); + HandleRotate?.Invoke(convertDragEventToAngleOfRotation(e)); + } + + private float convertDragEventToAngleOfRotation(DragEvent e) + { + // Adjust coordinate system to the center of SelectionBox + float startAngle = MathF.Atan2(e.LastMousePosition.Y - selectionBox.DrawHeight / 2, e.LastMousePosition.X - selectionBox.DrawWidth / 2); + float endAngle = MathF.Atan2(e.MousePosition.Y - selectionBox.DrawHeight / 2, e.MousePosition.X - selectionBox.DrawWidth / 2); + + return (endAngle - startAngle) * 180 / MathF.PI; + } } } diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs index a87c661f45..1f82f28380 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxScaleHandle.cs @@ -1,17 +1,28 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osuTK; namespace osu.Game.Screens.Edit.Compose.Components { public class SelectionBoxScaleHandle : SelectionBoxDragHandle { + public Action HandleScale { get; set; } + [BackgroundDependencyLoader] private void load() { Size = new Vector2(10); } + + protected override void OnDrag(DragEvent e) + { + HandleScale?.Invoke(e.Delta, Anchor); + base.OnDrag(e); + } } } From d76c674abc569c383bc8adbc7c4d9986a2029de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 Jan 2022 17:42:58 +0100 Subject: [PATCH 2/2] Add tooltip with relative rotation in degrees to rotation handles --- .../Components/SelectionBoxRotationHandle.cs | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs index 0db36d8902..22479bd9b3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBoxRotationHandle.cs @@ -3,21 +3,29 @@ using System; 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 osuTK; using osuTK.Graphics; namespace osu.Game.Screens.Edit.Compose.Components { - public class SelectionBoxRotationHandle : SelectionBoxDragHandle + public class SelectionBoxRotationHandle : SelectionBoxDragHandle, IHasTooltip { public Action HandleRotate { get; set; } + public LocalisableString TooltipText { get; private set; } + private SpriteIcon icon; + private readonly Bindable cumulativeRotation = new Bindable(); + [Resolved] private SelectionBox selectionBox { get; set; } @@ -40,16 +48,45 @@ namespace osu.Game.Screens.Edit.Compose.Components }); } + 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); } + protected override bool OnDragStart(DragStartEvent e) + { + bool handle = base.OnDragStart(e); + if (handle) + cumulativeRotation.Value = 0; + return handle; + } + protected override void OnDrag(DragEvent e) { base.OnDrag(e); - HandleRotate?.Invoke(convertDragEventToAngleOfRotation(e)); + + float instantaneousAngle = convertDragEventToAngleOfRotation(e); + cumulativeRotation.Value += instantaneousAngle; + + if (cumulativeRotation.Value < -180) + cumulativeRotation.Value += 360; + else if (cumulativeRotation.Value > 180) + cumulativeRotation.Value -= 360; + + HandleRotate?.Invoke(instantaneousAngle); + } + + protected override void OnDragEnd(DragEndEvent e) + { + base.OnDragEnd(e); + cumulativeRotation.Value = null; } private float convertDragEventToAngleOfRotation(DragEvent e) @@ -60,5 +97,10 @@ namespace osu.Game.Screens.Edit.Compose.Components return (endAngle - startAngle) * 180 / MathF.PI; } + + private void updateTooltipText() + { + TooltipText = cumulativeRotation.Value?.ToLocalisableString("0.0°") ?? default(LocalisableString); + } } }