1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 13:23:05 +08:00

Merge pull request #28089 from peppy/use-closest-origin

Automatically choose origin (along with anchor) to make skin editor placement easier for users
This commit is contained in:
Bartłomiej Dach 2024-05-06 14:57:34 +02:00 committed by GitHub
commit d7a0fdce07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 20 deletions

View File

@ -40,7 +40,9 @@ namespace osu.Game.Overlays.SkinEditor
public override bool Contains(Vector2 screenSpacePos) => drawableQuad.Contains(screenSpacePos); public override bool Contains(Vector2 screenSpacePos) => drawableQuad.Contains(screenSpacePos);
public override Vector2 ScreenSpaceSelectionPoint => drawable.ToScreenSpace(drawable.OriginPosition); public override Vector2 ScreenSpaceSelectionPoint =>
// Important to use a stable position (not based on origin) as origin may be automatically updated during drag operations.
drawable.ScreenSpaceDrawQuad.Centre;
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) =>
drawableQuad.Contains(screenSpacePos); drawableQuad.Contains(screenSpacePos);

View File

@ -457,7 +457,7 @@ namespace osu.Game.Overlays.SkinEditor
} }
SelectedComponents.Add(component); SelectedComponents.Add(component);
SkinSelectionHandler.ApplyClosestAnchor(drawableComponent); SkinSelectionHandler.ApplyClosestAnchorOrigin(drawableComponent);
return true; return true;
} }

View File

@ -23,6 +23,8 @@ namespace osu.Game.Overlays.SkinEditor
{ {
public partial class SkinSelectionHandler : SelectionHandler<ISerialisableDrawable> public partial class SkinSelectionHandler : SelectionHandler<ISerialisableDrawable>
{ {
private OsuMenuItem originMenu = null!;
[Resolved] [Resolved]
private SkinEditor skinEditor { get; set; } = null!; private SkinEditor skinEditor { get; set; } = null!;
@ -137,7 +139,7 @@ namespace osu.Game.Overlays.SkinEditor
var drawableItem = (Drawable)b.Item; var drawableItem = (Drawable)b.Item;
// each drawable's relative position should be maintained in the scaled quad. // each drawable's relative position should be maintained in the scaled quad.
var screenPosition = b.ScreenSpaceSelectionPoint; var screenPosition = drawableItem.ToScreenSpace(drawableItem.OriginPosition);
var relativePositionInOriginal = var relativePositionInOriginal =
new Vector2( new Vector2(
@ -202,17 +204,22 @@ namespace osu.Game.Overlays.SkinEditor
var item = c.Item; var item = c.Item;
Drawable drawable = (Drawable)item; Drawable drawable = (Drawable)item;
if (!item.UsesFixedAnchor)
ApplyClosestAnchorOrigin(drawable);
drawable.Position += drawable.ScreenSpaceDeltaToParentSpace(moveEvent.ScreenSpaceDelta); drawable.Position += drawable.ScreenSpaceDeltaToParentSpace(moveEvent.ScreenSpaceDelta);
if (item.UsesFixedAnchor) continue;
ApplyClosestAnchor(drawable);
} }
return true; return true;
} }
public static void ApplyClosestAnchor(Drawable drawable) => applyAnchor(drawable, getClosestAnchor(drawable)); public static void ApplyClosestAnchorOrigin(Drawable drawable)
{
var closest = getClosestAnchor(drawable);
applyAnchor(drawable, closest);
applyOrigin(drawable, closest);
}
protected override void OnSelectionChanged() protected override void OnSelectionChanged()
{ {
@ -243,10 +250,15 @@ namespace osu.Game.Overlays.SkinEditor
.ToArray() .ToArray()
}; };
yield return new OsuMenuItem("Origin") yield return originMenu = new OsuMenuItem("Origin");
closestItem.State.BindValueChanged(s =>
{ {
Items = createAnchorItems((d, o) => ((Drawable)d).Origin == o, applyOrigins).ToArray() // For UX simplicity, origin should only be user-editable when "closest" anchor mode is disabled.
}; originMenu.Items = s.NewValue == TernaryState.True
? Array.Empty<MenuItem>()
: createAnchorItems((d, o) => ((Drawable)d).Origin == o, applyOrigins).ToArray();
}, true);
yield return new OsuMenuItemSpacer(); yield return new OsuMenuItemSpacer();
@ -325,15 +337,10 @@ namespace osu.Game.Overlays.SkinEditor
{ {
var drawable = (Drawable)item; var drawable = (Drawable)item;
if (origin == drawable.Origin) continue; applyOrigin(drawable, origin);
var previousOrigin = drawable.OriginPosition; if (!item.UsesFixedAnchor)
drawable.Origin = origin; ApplyClosestAnchorOrigin(drawable);
drawable.Position += drawable.OriginPosition - previousOrigin;
if (item.UsesFixedAnchor) continue;
ApplyClosestAnchor(drawable);
} }
OnOperationEnded(); OnOperationEnded();
@ -368,7 +375,7 @@ namespace osu.Game.Overlays.SkinEditor
foreach (var item in SelectedItems) foreach (var item in SelectedItems)
{ {
item.UsesFixedAnchor = false; item.UsesFixedAnchor = false;
ApplyClosestAnchor((Drawable)item); ApplyClosestAnchorOrigin((Drawable)item);
} }
OnOperationEnded(); OnOperationEnded();
@ -414,6 +421,15 @@ namespace osu.Game.Overlays.SkinEditor
drawable.Position -= drawable.AnchorPosition - previousAnchor; drawable.Position -= drawable.AnchorPosition - previousAnchor;
} }
private static void applyOrigin(Drawable drawable, Anchor origin)
{
if (origin == drawable.Origin) return;
var previousOrigin = drawable.OriginPosition;
drawable.Origin = origin;
drawable.Position += drawable.OriginPosition - previousOrigin;
}
private static void adjustScaleFromAnchor(ref Vector2 scale, Anchor reference) private static void adjustScaleFromAnchor(ref Vector2 scale, Anchor reference)
{ {
// cancel out scale in axes we don't care about (based on which drag handle was used). // cancel out scale in axes we don't care about (based on which drag handle was used).