Merge branch 'master' into editor-new-change-diff

This commit is contained in:
Bartłomiej Dach 2021-09-06 21:42:32 +02:00
commit d13e00ed42
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497
4 changed files with 146 additions and 28 deletions

View File

@ -1,14 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Input.Handlers.Tablet;
using osu.Framework.Platform; using osu.Framework.Testing;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Settings;
using osu.Game.Overlays.Settings.Sections.Input; using osu.Game.Overlays.Settings.Sections.Input;
using osuTK; using osuTK;
@ -17,22 +18,34 @@ namespace osu.Game.Tests.Visual.Settings
[TestFixture] [TestFixture]
public class TestSceneTabletSettings : OsuTestScene public class TestSceneTabletSettings : OsuTestScene
{ {
[BackgroundDependencyLoader] private TestTabletHandler tabletHandler;
private void load(GameHost host) private TabletSettings settings;
{
var tabletHandler = new TestTabletHandler();
AddRange(new Drawable[] [SetUpSteps]
public void SetUpSteps()
{
AddStep("create settings", () =>
{ {
new TabletSettings(tabletHandler) tabletHandler = new TestTabletHandler();
Children = new Drawable[]
{ {
RelativeSizeAxes = Axes.None, settings = new TabletSettings(tabletHandler)
Width = SettingsPanel.PANEL_WIDTH, {
Anchor = Anchor.TopCentre, RelativeSizeAxes = Axes.None,
Origin = Anchor.TopCentre, Width = SettingsPanel.PANEL_WIDTH,
} Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
}
};
}); });
AddStep("set square size", () => tabletHandler.SetTabletSize(new Vector2(100, 100)));
}
[Test]
public void TestVariousTabletSizes()
{
AddStep("Test with wide tablet", () => tabletHandler.SetTabletSize(new Vector2(160, 100))); AddStep("Test with wide tablet", () => tabletHandler.SetTabletSize(new Vector2(160, 100)));
AddStep("Test with square tablet", () => tabletHandler.SetTabletSize(new Vector2(300, 300))); AddStep("Test with square tablet", () => tabletHandler.SetTabletSize(new Vector2(300, 300)));
AddStep("Test with tall tablet", () => tabletHandler.SetTabletSize(new Vector2(100, 300))); AddStep("Test with tall tablet", () => tabletHandler.SetTabletSize(new Vector2(100, 300)));
@ -40,6 +53,71 @@ namespace osu.Game.Tests.Visual.Settings
AddStep("Test no tablet present", () => tabletHandler.SetTabletSize(Vector2.Zero)); AddStep("Test no tablet present", () => tabletHandler.SetTabletSize(Vector2.Zero));
} }
[Test]
public void TestWideAspectRatioValidity()
{
AddStep("Test with wide tablet", () => tabletHandler.SetTabletSize(new Vector2(160, 100)));
AddStep("Reset to full area", () => settings.ChildrenOfType<DangerousSettingsButton>().First().TriggerClick());
ensureValid();
AddStep("rotate 10", () => tabletHandler.Rotation.Value = 10);
ensureInvalid();
AddStep("scale down", () => tabletHandler.AreaSize.Value *= 0.9f);
ensureInvalid();
AddStep("scale down", () => tabletHandler.AreaSize.Value *= 0.9f);
ensureInvalid();
AddStep("scale down", () => tabletHandler.AreaSize.Value *= 0.9f);
ensureValid();
}
[Test]
public void TestRotationValidity()
{
AddAssert("area valid", () => settings.AreaSelection.IsWithinBounds);
AddStep("rotate 90", () => tabletHandler.Rotation.Value = 90);
ensureValid();
AddStep("rotate 180", () => tabletHandler.Rotation.Value = 180);
ensureValid();
AddStep("rotate 270", () => tabletHandler.Rotation.Value = 270);
ensureValid();
AddStep("rotate 360", () => tabletHandler.Rotation.Value = 360);
ensureValid();
AddStep("rotate 0", () => tabletHandler.Rotation.Value = 0);
ensureValid();
AddStep("rotate 45", () => tabletHandler.Rotation.Value = 45);
ensureInvalid();
AddStep("rotate 0", () => tabletHandler.Rotation.Value = 0);
ensureValid();
}
[Test]
public void TestOffsetValidity()
{
ensureValid();
AddStep("move right", () => tabletHandler.AreaOffset.Value = Vector2.Zero);
ensureInvalid();
AddStep("move back", () => tabletHandler.AreaOffset.Value = tabletHandler.AreaSize.Value / 2);
ensureValid();
}
private void ensureValid() => AddAssert("area valid", () => settings.AreaSelection.IsWithinBounds);
private void ensureInvalid() => AddAssert("area invalid", () => !settings.AreaSelection.IsWithinBounds);
public class TestTabletHandler : ITabletHandler public class TestTabletHandler : ITabletHandler
{ {
public Bindable<Vector2> AreaOffset { get; } = new Bindable<Vector2>(); public Bindable<Vector2> AreaOffset { get; } = new Bindable<Vector2>();

View File

@ -8,8 +8,9 @@ namespace osu.Game.Online.API.Requests
{ {
public class GetUserRequest : APIRequest<User> public class GetUserRequest : APIRequest<User>
{ {
private readonly string userIdentifier; private readonly string lookup;
public readonly RulesetInfo Ruleset; public readonly RulesetInfo Ruleset;
private readonly LookupType lookupType;
/// <summary> /// <summary>
/// Gets the currently logged-in user. /// Gets the currently logged-in user.
@ -25,7 +26,8 @@ namespace osu.Game.Online.API.Requests
/// <param name="ruleset">The ruleset to get the user's info for.</param> /// <param name="ruleset">The ruleset to get the user's info for.</param>
public GetUserRequest(long? userId = null, RulesetInfo ruleset = null) public GetUserRequest(long? userId = null, RulesetInfo ruleset = null)
{ {
this.userIdentifier = userId.ToString(); lookup = userId.ToString();
lookupType = LookupType.Id;
Ruleset = ruleset; Ruleset = ruleset;
} }
@ -36,10 +38,17 @@ namespace osu.Game.Online.API.Requests
/// <param name="ruleset">The ruleset to get the user's info for.</param> /// <param name="ruleset">The ruleset to get the user's info for.</param>
public GetUserRequest(string username = null, RulesetInfo ruleset = null) public GetUserRequest(string username = null, RulesetInfo ruleset = null)
{ {
this.userIdentifier = username; lookup = username;
lookupType = LookupType.Username;
Ruleset = ruleset; Ruleset = ruleset;
} }
protected override string Target => userIdentifier != null ? $@"users/{userIdentifier}/{Ruleset?.ShortName}" : $@"me/{Ruleset?.ShortName}"; protected override string Target => lookup != null ? $@"users/{lookup}/{Ruleset?.ShortName}?k={lookupType.ToString().ToLower()}" : $@"me/{Ruleset?.ShortName}";
private enum LookupType
{
Id,
Username
}
} }
} }

View File

@ -4,10 +4,13 @@
using System; using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.MatrixExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Handlers.Tablet; using osu.Framework.Input.Handlers.Tablet;
using osu.Framework.Utils;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osuTK; using osuTK;
@ -17,6 +20,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
public class TabletAreaSelection : CompositeDrawable public class TabletAreaSelection : CompositeDrawable
{ {
public bool IsWithinBounds { get; private set; }
private readonly ITabletHandler handler; private readonly ITabletHandler handler;
private Container tabletContainer; private Container tabletContainer;
@ -109,29 +114,30 @@ namespace osu.Game.Overlays.Settings.Sections.Input
areaOffset.BindTo(handler.AreaOffset); areaOffset.BindTo(handler.AreaOffset);
areaOffset.BindValueChanged(val => areaOffset.BindValueChanged(val =>
{ {
usableAreaContainer.MoveTo(val.NewValue, 100, Easing.OutQuint) usableAreaContainer.MoveTo(val.NewValue, 100, Easing.OutQuint);
.OnComplete(_ => checkBounds()); // required as we are using SSDQ. checkBounds();
}, true); }, true);
areaSize.BindTo(handler.AreaSize); areaSize.BindTo(handler.AreaSize);
areaSize.BindValueChanged(val => areaSize.BindValueChanged(val =>
{ {
usableAreaContainer.ResizeTo(val.NewValue, 100, Easing.OutQuint) usableAreaContainer.ResizeTo(val.NewValue, 100, Easing.OutQuint);
.OnComplete(_ => checkBounds()); // required as we are using SSDQ.
int x = (int)val.NewValue.X; int x = (int)val.NewValue.X;
int y = (int)val.NewValue.Y; int y = (int)val.NewValue.Y;
int commonDivider = greatestCommonDivider(x, y); int commonDivider = greatestCommonDivider(x, y);
usableAreaText.Text = $"{(float)x / commonDivider}:{(float)y / commonDivider}"; usableAreaText.Text = $"{(float)x / commonDivider}:{(float)y / commonDivider}";
checkBounds();
}, true); }, true);
rotation.BindTo(handler.Rotation); rotation.BindTo(handler.Rotation);
rotation.BindValueChanged(val => rotation.BindValueChanged(val =>
{ {
usableAreaContainer.RotateTo(val.NewValue, 100, Easing.OutQuint);
tabletContainer.RotateTo(-val.NewValue, 800, Easing.OutQuint); tabletContainer.RotateTo(-val.NewValue, 800, Easing.OutQuint);
usableAreaContainer.RotateTo(val.NewValue, 100, Easing.OutQuint)
.OnComplete(_ => checkBounds()); // required as we are using SSDQ. checkBounds();
}, true); }, true);
tablet.BindTo(handler.Tablet); tablet.BindTo(handler.Tablet);
@ -169,12 +175,35 @@ namespace osu.Game.Overlays.Settings.Sections.Input
if (tablet.Value == null) if (tablet.Value == null)
return; return;
var usableSsdq = usableAreaContainer.ScreenSpaceDrawQuad; // allow for some degree of floating point error, as we don't care about being perfect here.
const float lenience = 0.5f;
bool isWithinBounds = tabletContainer.ScreenSpaceDrawQuad.Contains(usableSsdq.TopLeft + new Vector2(1)) && var tabletArea = new Quad(-lenience, -lenience, tablet.Value.Size.X + lenience * 2, tablet.Value.Size.Y + lenience * 2);
tabletContainer.ScreenSpaceDrawQuad.Contains(usableSsdq.BottomRight - new Vector2(1));
usableFill.FadeColour(isWithinBounds ? colour.Blue : colour.RedLight, 100); var halfUsableArea = areaSize.Value / 2;
var offset = areaOffset.Value;
var usableAreaQuad = new Quad(
new Vector2(-halfUsableArea.X, -halfUsableArea.Y),
new Vector2(halfUsableArea.X, -halfUsableArea.Y),
new Vector2(-halfUsableArea.X, halfUsableArea.Y),
new Vector2(halfUsableArea.X, halfUsableArea.Y)
);
var matrix = Matrix3.Identity;
MatrixExtensions.TranslateFromLeft(ref matrix, offset);
MatrixExtensions.RotateFromLeft(ref matrix, MathUtils.DegreesToRadians(rotation.Value));
usableAreaQuad *= matrix;
IsWithinBounds =
tabletArea.Contains(usableAreaQuad.TopLeft) &&
tabletArea.Contains(usableAreaQuad.TopRight) &&
tabletArea.Contains(usableAreaQuad.BottomLeft) &&
tabletArea.Contains(usableAreaQuad.BottomRight);
usableFill.FadeColour(IsWithinBounds ? colour.Blue : colour.RedLight, 100);
} }
protected override void Update() protected override void Update()

View File

@ -20,6 +20,8 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{ {
public class TabletSettings : SettingsSubsection public class TabletSettings : SettingsSubsection
{ {
public TabletAreaSelection AreaSelection { get; private set; }
private readonly ITabletHandler tabletHandler; private readonly ITabletHandler tabletHandler;
private readonly Bindable<bool> enabled = new BindableBool(true); private readonly Bindable<bool> enabled = new BindableBool(true);
@ -121,7 +123,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
Direction = FillDirection.Vertical, Direction = FillDirection.Vertical,
Children = new Drawable[] Children = new Drawable[]
{ {
new TabletAreaSelection(tabletHandler) AreaSelection = new TabletAreaSelection(tabletHandler)
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Height = 300, Height = 300,