mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 16:27:26 +08:00
Merge branch 'master' into fix-storyboard-sample-rate
This commit is contained in:
commit
e5a6564034
@ -51,8 +51,8 @@
|
||||
<Reference Include="Java.Interop" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.211.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.223.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.304.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.304.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Transitive Dependencies">
|
||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||
|
@ -45,10 +45,5 @@ namespace osu.Game.Rulesets.Mania
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class TimeSlider : OsuSliderBar<double>
|
||||
{
|
||||
public override LocalisableString TooltipText => Current.Value.ToString(@"N0") + "ms";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDisplay()
|
||||
public void TestCalibrationFromZero()
|
||||
{
|
||||
const double average_error = -4.5;
|
||||
|
||||
@ -62,11 +62,39 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
};
|
||||
});
|
||||
|
||||
AddAssert("Has calibration button", () => offsetControl.ChildrenOfType<SettingsButton>().Any());
|
||||
AddUntilStep("Has calibration button", () => offsetControl.ChildrenOfType<SettingsButton>().Any());
|
||||
AddStep("Press button", () => offsetControl.ChildrenOfType<SettingsButton>().Single().TriggerClick());
|
||||
AddAssert("Offset is adjusted", () => offsetControl.Current.Value == -average_error);
|
||||
|
||||
AddAssert("Button is disabled", () => !offsetControl.ChildrenOfType<SettingsButton>().Single().Enabled.Value);
|
||||
AddUntilStep("Button is disabled", () => !offsetControl.ChildrenOfType<SettingsButton>().Single().Enabled.Value);
|
||||
AddStep("Remove reference score", () => offsetControl.ReferenceScore.Value = null);
|
||||
AddAssert("No calibration button", () => !offsetControl.ChildrenOfType<SettingsButton>().Any());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When a beatmap offset was already set, the calibration should take it into account.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCalibrationFromNonZero()
|
||||
{
|
||||
const double average_error = -4.5;
|
||||
const double initial_offset = -2;
|
||||
|
||||
AddStep("Set offset non-neutral", () => offsetControl.Current.Value = initial_offset);
|
||||
AddAssert("No calibration button", () => !offsetControl.ChildrenOfType<SettingsButton>().Any());
|
||||
AddStep("Set reference score", () =>
|
||||
{
|
||||
offsetControl.ReferenceScore.Value = new ScoreInfo
|
||||
{
|
||||
HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents(average_error)
|
||||
};
|
||||
});
|
||||
|
||||
AddUntilStep("Has calibration button", () => offsetControl.ChildrenOfType<SettingsButton>().Any());
|
||||
AddStep("Press button", () => offsetControl.ChildrenOfType<SettingsButton>().Single().TriggerClick());
|
||||
AddAssert("Offset is adjusted", () => offsetControl.Current.Value == initial_offset - average_error);
|
||||
|
||||
AddUntilStep("Button is disabled", () => !offsetControl.ChildrenOfType<SettingsButton>().Single().Enabled.Value);
|
||||
AddStep("Remove reference score", () => offsetControl.ReferenceScore.Value = null);
|
||||
AddAssert("No calibration button", () => !offsetControl.ChildrenOfType<SettingsButton>().Any());
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Ranking.Statistics;
|
||||
@ -17,22 +18,33 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
{
|
||||
public class TestSceneHitEventTimingDistributionGraph : OsuTestScene
|
||||
{
|
||||
private HitEventTimingDistributionGraph graph;
|
||||
|
||||
private static readonly HitObject placeholder_object = new HitCircle();
|
||||
|
||||
[Test]
|
||||
public void TestManyDistributedEvents()
|
||||
{
|
||||
createTest(CreateDistributedHitEvents());
|
||||
AddStep("add adjustment", () => graph.UpdateOffset(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestManyDistributedEventsOffset()
|
||||
{
|
||||
createTest(CreateDistributedHitEvents(-3.5));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAroundCentre()
|
||||
{
|
||||
createTest(Enumerable.Range(-150, 300).Select(i => new HitEvent(i / 50f, HitResult.Perfect, new HitCircle(), new HitCircle(), null)).ToList());
|
||||
createTest(Enumerable.Range(-150, 300).Select(i => new HitEvent(i / 50f, HitResult.Perfect, placeholder_object, placeholder_object, null)).ToList());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestZeroTimeOffset()
|
||||
{
|
||||
createTest(Enumerable.Range(0, 100).Select(_ => new HitEvent(0, HitResult.Perfect, new HitCircle(), new HitCircle(), null)).ToList());
|
||||
createTest(Enumerable.Range(0, 100).Select(_ => new HitEvent(0, HitResult.Perfect, placeholder_object, placeholder_object, null)).ToList());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -47,9 +59,9 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
createTest(Enumerable.Range(0, 100).Select(i =>
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
return new HitEvent(0, HitResult.Perfect, new HitCircle(), new HitCircle(), null);
|
||||
return new HitEvent(0, HitResult.Perfect, placeholder_object, placeholder_object, null);
|
||||
|
||||
return new HitEvent(30, HitResult.Miss, new HitCircle(), new HitCircle(), null);
|
||||
return new HitEvent(30, HitResult.Miss, placeholder_object, placeholder_object, null);
|
||||
}).ToList());
|
||||
}
|
||||
|
||||
@ -62,7 +74,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4Extensions.FromHex("#333")
|
||||
},
|
||||
new HitEventTimingDistributionGraph(events)
|
||||
graph = new HitEventTimingDistributionGraph(events)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -77,10 +89,10 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
|
||||
for (int i = 0; i < range * 2; i++)
|
||||
{
|
||||
int count = (int)(Math.Pow(range - Math.Abs(i - range), 2));
|
||||
int count = (int)(Math.Pow(range - Math.Abs(i - range), 2)) / 10;
|
||||
|
||||
for (int j = 0; j < count; j++)
|
||||
hitEvents.Add(new HitEvent(centre + i - range, HitResult.Perfect, new HitCircle(), new HitCircle(), null));
|
||||
hitEvents.Add(new HitEvent(centre + i - range, HitResult.Perfect, placeholder_object, placeholder_object, null));
|
||||
}
|
||||
|
||||
return hitEvents;
|
||||
|
@ -140,7 +140,7 @@ namespace osu.Game.Configuration
|
||||
|
||||
SetDefault(OsuSetting.UIScale, 1f, 0.8f, 1.6f, 0.01f);
|
||||
|
||||
SetDefault(OsuSetting.UIHoldActivationDelay, 200f, 0f, 500f, 50f);
|
||||
SetDefault(OsuSetting.UIHoldActivationDelay, 200.0, 0.0, 500.0, 50.0);
|
||||
|
||||
SetDefault(OsuSetting.IntroSequence, IntroSequence.Triangles);
|
||||
|
||||
@ -270,7 +270,13 @@ namespace osu.Game.Configuration
|
||||
MouseDisableButtons,
|
||||
MouseDisableWheel,
|
||||
ConfineMouseMode,
|
||||
|
||||
/// <summary>
|
||||
/// Globally applied audio offset.
|
||||
/// This is added to the audio track's current time. Higher values will cause gameplay to occur earlier, relative to the audio track.
|
||||
/// </summary>
|
||||
AudioOffset,
|
||||
|
||||
VolumeInactive,
|
||||
MenuMusic,
|
||||
MenuVoice,
|
||||
|
@ -30,12 +30,12 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
public Bindable<double> Progress = new BindableDouble();
|
||||
|
||||
private Bindable<float> holdActivationDelay;
|
||||
private Bindable<double> holdActivationDelay;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
holdActivationDelay = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay);
|
||||
holdActivationDelay = config.GetBindable<double>(OsuSetting.UIHoldActivationDelay);
|
||||
}
|
||||
|
||||
protected void BeginConfirm()
|
||||
|
@ -140,6 +140,7 @@ namespace osu.Game.Graphics.Cursor
|
||||
// Scale to [-0.75, 0.75] so that the sample isn't fully panned left or right (sounds weird)
|
||||
channel.Balance.Value = ((activeCursor.X / DrawWidth) * 2 - 1) * 0.75;
|
||||
channel.Frequency.Value = baseFrequency - (random_range / 2f) + RNG.NextDouble(random_range);
|
||||
channel.Volume.Value = baseFrequency;
|
||||
|
||||
channel.Play();
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
CurrentNumber.BindValueChanged(current => updateTooltipText(current.NewValue), true);
|
||||
CurrentNumber.BindValueChanged(current => TooltipText = getTooltipText(current.NewValue), true);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
@ -178,7 +178,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
base.OnUserChange(value);
|
||||
playSample(value);
|
||||
updateTooltipText(value);
|
||||
TooltipText = getTooltipText(value);
|
||||
}
|
||||
|
||||
private void playSample(T value)
|
||||
@ -203,28 +203,22 @@ namespace osu.Game.Graphics.UserInterface
|
||||
channel.Play();
|
||||
}
|
||||
|
||||
private void updateTooltipText(T value)
|
||||
private LocalisableString getTooltipText(T value)
|
||||
{
|
||||
if (CurrentNumber.IsInteger)
|
||||
TooltipText = value.ToInt32(NumberFormatInfo.InvariantInfo).ToString("N0");
|
||||
else
|
||||
{
|
||||
double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo);
|
||||
return value.ToInt32(NumberFormatInfo.InvariantInfo).ToString("N0");
|
||||
|
||||
if (DisplayAsPercentage)
|
||||
{
|
||||
TooltipText = floatValue.ToString("0%");
|
||||
}
|
||||
else
|
||||
{
|
||||
decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits);
|
||||
double floatValue = value.ToDouble(NumberFormatInfo.InvariantInfo);
|
||||
|
||||
// Find the number of significant digits (we could have less than 5 after normalize())
|
||||
int significantDigits = FormatUtils.FindPrecision(decimalPrecision);
|
||||
if (DisplayAsPercentage)
|
||||
return floatValue.ToString("0%");
|
||||
|
||||
TooltipText = floatValue.ToString($"N{significantDigits}");
|
||||
}
|
||||
}
|
||||
decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits);
|
||||
|
||||
// Find the number of significant digits (we could have less than 5 after normalize())
|
||||
int significantDigits = FormatUtils.FindPrecision(decimalPrecision);
|
||||
|
||||
return floatValue.ToString($"N{significantDigits}");
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
|
15
osu.Game/Graphics/UserInterface/TimeSlider.cs
Normal file
15
osu.Game/Graphics/UserInterface/TimeSlider.cs
Normal file
@ -0,0 +1,15 @@
|
||||
// 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.
|
||||
|
||||
using osu.Framework.Localisation;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// A slider bar which displays a millisecond time value.
|
||||
/// </summary>
|
||||
public class TimeSlider : OsuSliderBar<double>
|
||||
{
|
||||
public override LocalisableString TooltipText => $"{Current.Value:N0} ms";
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
||||
set => Component.Text = value;
|
||||
}
|
||||
|
||||
public Container TabbableContentContainer
|
||||
public CompositeDrawable TabbableContentContainer
|
||||
{
|
||||
set => Component.TabbableContentContainer = value;
|
||||
}
|
||||
|
@ -29,6 +29,16 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString CalibrateUsingLastPlay => new TranslatableString(getKey(@"calibrate_using_last_play"), @"Calibrate using last play");
|
||||
|
||||
/// <summary>
|
||||
/// "(hit objects appear later)"
|
||||
/// </summary>
|
||||
public static LocalisableString HitObjectsAppearLater => new TranslatableString(getKey(@"hit_objects_appear_later"), @"(hit objects appear later)");
|
||||
|
||||
/// <summary>
|
||||
/// "(hit objects appear earlier)"
|
||||
/// </summary>
|
||||
public static LocalisableString HitObjectsAppearEarlier => new TranslatableString(getKey(@"hit_objects_appear_earlier"), @"(hit objects appear earlier)");
|
||||
|
||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
public static LocalisableString Resolution => new TranslatableString(getKey(@"resolution"), @"Resolution");
|
||||
|
||||
/// <summary>
|
||||
/// "Display"
|
||||
/// </summary>
|
||||
public static LocalisableString Display => new TranslatableString(getKey(@"display"), @"Display");
|
||||
|
||||
/// <summary>
|
||||
/// "UI scaling"
|
||||
/// </summary>
|
||||
|
@ -1,6 +1,8 @@
|
||||
// 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.
|
||||
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Online.API.Requests
|
||||
@ -8,14 +10,14 @@ namespace osu.Game.Online.API.Requests
|
||||
public class GetWikiRequest : APIRequest<APIWikiPage>
|
||||
{
|
||||
private readonly string path;
|
||||
private readonly string locale;
|
||||
private readonly Language language;
|
||||
|
||||
public GetWikiRequest(string path, string locale = "en")
|
||||
public GetWikiRequest(string path, Language language = Language.en)
|
||||
{
|
||||
this.path = path;
|
||||
this.locale = locale;
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
protected override string Target => $"wiki/{locale}/{path}";
|
||||
protected override string Target => $"wiki/{language.ToCultureCode()}/{path}";
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
@ -63,11 +64,17 @@ namespace osu.Game.Overlays.Profile.Header
|
||||
};
|
||||
}
|
||||
|
||||
private CancellationTokenSource cancellationTokenSource;
|
||||
|
||||
private void updateDisplay(APIUser user)
|
||||
{
|
||||
var badges = user.Badges;
|
||||
cancellationTokenSource?.Cancel();
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
badgeFlowContainer.Clear();
|
||||
|
||||
var badges = user.Badges;
|
||||
|
||||
if (badges?.Length > 0)
|
||||
{
|
||||
Show();
|
||||
@ -79,7 +86,7 @@ namespace osu.Game.Overlays.Profile.Header
|
||||
{
|
||||
// load in stable order regardless of async load order.
|
||||
badgeFlowContainer.Insert(displayIndex, asyncBadge);
|
||||
});
|
||||
}, cancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -87,5 +94,11 @@ namespace osu.Game.Overlays.Profile.Header
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
cancellationTokenSource?.Cancel();
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsSlider<double, OffsetSlider>
|
||||
new SettingsSlider<double, TimeSlider>
|
||||
{
|
||||
LabelText = AudioSettingsStrings.AudioOffset,
|
||||
Current = config.GetBindable<double>(OsuSetting.AudioOffset),
|
||||
@ -35,10 +35,5 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class OffsetSlider : OsuSliderBar<double>
|
||||
{
|
||||
public override LocalisableString TooltipText => Current.Value.ToString(@"0ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
|
||||
private FillFlowContainer<SettingsSlider<float>> scalingSettings;
|
||||
|
||||
private readonly IBindable<Display> currentDisplay = new Bindable<Display>();
|
||||
private readonly Bindable<Display> currentDisplay = new Bindable<Display>();
|
||||
private readonly IBindableList<WindowMode> windowModes = new BindableList<WindowMode>();
|
||||
|
||||
private Bindable<ScalingMode> scalingMode;
|
||||
@ -39,6 +39,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
private OsuGameBase game { get; set; }
|
||||
|
||||
private SettingsDropdown<Size> resolutionDropdown;
|
||||
private SettingsDropdown<Display> displayDropdown;
|
||||
private SettingsDropdown<WindowMode> windowModeDropdown;
|
||||
|
||||
private Bindable<float> scalingPositionX;
|
||||
@ -72,6 +73,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
ItemSource = windowModes,
|
||||
Current = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
|
||||
},
|
||||
displayDropdown = new DisplaySettingsDropdown
|
||||
{
|
||||
LabelText = GraphicsSettingsStrings.Display,
|
||||
Items = host.Window?.Displays,
|
||||
Current = currentDisplay,
|
||||
},
|
||||
resolutionDropdown = new ResolutionSettingsDropdown
|
||||
{
|
||||
LabelText = GraphicsSettingsStrings.Resolution,
|
||||
@ -142,7 +149,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
|
||||
windowModeDropdown.Current.BindValueChanged(mode =>
|
||||
{
|
||||
updateResolutionDropdown();
|
||||
updateDisplayModeDropdowns();
|
||||
|
||||
windowModeDropdown.WarningText = mode.NewValue != WindowMode.Fullscreen ? GraphicsSettingsStrings.NotFullscreenNote : default;
|
||||
}, true);
|
||||
@ -168,7 +175,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
.Distinct());
|
||||
}
|
||||
|
||||
updateResolutionDropdown();
|
||||
updateDisplayModeDropdowns();
|
||||
}), true);
|
||||
|
||||
scalingMode.BindValueChanged(mode =>
|
||||
@ -183,12 +190,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
// initial update bypasses transforms
|
||||
updateScalingModeVisibility();
|
||||
|
||||
void updateResolutionDropdown()
|
||||
void updateDisplayModeDropdowns()
|
||||
{
|
||||
if (resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen)
|
||||
resolutionDropdown.Show();
|
||||
else
|
||||
resolutionDropdown.Hide();
|
||||
|
||||
if (displayDropdown.Items.Count() > 1)
|
||||
displayDropdown.Show();
|
||||
else
|
||||
displayDropdown.Hide();
|
||||
}
|
||||
|
||||
void updateScalingModeVisibility()
|
||||
@ -243,6 +255,19 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
public override LocalisableString TooltipText => base.TooltipText + "x";
|
||||
}
|
||||
|
||||
private class DisplaySettingsDropdown : SettingsDropdown<Display>
|
||||
{
|
||||
protected override OsuDropdown<Display> CreateDropdown() => new DisplaySettingsDropdownControl();
|
||||
|
||||
private class DisplaySettingsDropdownControl : DropdownControl
|
||||
{
|
||||
protected override LocalisableString GenerateItemText(Display item)
|
||||
{
|
||||
return $"{item.Index}: {item.Name} ({item.Bounds.Width}x{item.Bounds.Height})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ResolutionSettingsDropdown : SettingsDropdown<Size>
|
||||
{
|
||||
protected override OsuDropdown<Size> CreateDropdown() => new ResolutionDropdownControl();
|
||||
|
@ -35,18 +35,13 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
||||
LabelText = UserInterfaceStrings.Parallax,
|
||||
Current = config.GetBindable<bool>(OsuSetting.MenuParallax)
|
||||
},
|
||||
new SettingsSlider<float, TimeSlider>
|
||||
new SettingsSlider<double, TimeSlider>
|
||||
{
|
||||
LabelText = UserInterfaceStrings.HoldToConfirmActivationTime,
|
||||
Current = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay),
|
||||
Current = config.GetBindable<double>(OsuSetting.UIHoldActivationDelay),
|
||||
KeyboardStep = 50
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private class TimeSlider : OsuSliderBar<float>
|
||||
{
|
||||
public override LocalisableString TooltipText => Current.Value.ToString(@"N0") + "ms";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
@ -100,7 +101,12 @@ namespace osu.Game.Overlays
|
||||
cancellationToken?.Cancel();
|
||||
request?.Cancel();
|
||||
|
||||
request = new GetWikiRequest(e.NewValue);
|
||||
string[] values = e.NewValue.Split('/', 2);
|
||||
|
||||
if (values.Length > 1 && LanguageExtensions.TryParseCultureCode(values[0], out var language))
|
||||
request = new GetWikiRequest(values[1], language);
|
||||
else
|
||||
request = new GetWikiRequest(e.NewValue);
|
||||
|
||||
Loading.Show();
|
||||
|
||||
|
@ -75,9 +75,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
FillFlowContainer flow;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
flow = new FillFlowContainer
|
||||
{
|
||||
Width = 200,
|
||||
Direction = FillDirection.Vertical,
|
||||
@ -94,6 +96,9 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
}
|
||||
};
|
||||
|
||||
bank.TabbableContentContainer = flow;
|
||||
volume.TabbableContentContainer = flow;
|
||||
|
||||
// if the piece belongs to a currently selected object, assume that the user wants to change all selected objects.
|
||||
// if the piece belongs to an unselected object, operate on that object alone, independently of the selection.
|
||||
var relevantObjects = (beatmap.SelectedHitObjects.Contains(hitObject) ? beatmap.SelectedHitObjects : hitObject.Yield()).ToArray();
|
||||
|
@ -32,6 +32,11 @@ namespace osu.Game.Screens.Edit.Timing
|
||||
set => slider.KeyboardStep = value;
|
||||
}
|
||||
|
||||
public CompositeDrawable TabbableContentContainer
|
||||
{
|
||||
set => textBox.TabbableContentContainer = value;
|
||||
}
|
||||
|
||||
private readonly BindableWithCurrent<T?> current = new BindableWithCurrent<T?>();
|
||||
|
||||
public Bindable<T?> Current
|
||||
|
@ -66,7 +66,7 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
protected override BackgroundScreen CreateBackground() => background;
|
||||
|
||||
private Bindable<float> holdDelay;
|
||||
private Bindable<double> holdDelay;
|
||||
private Bindable<bool> loginDisplayed;
|
||||
|
||||
private ExitConfirmOverlay exitConfirmOverlay;
|
||||
@ -77,7 +77,7 @@ namespace osu.Game.Screens.Menu
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(BeatmapListingOverlay beatmapListing, SettingsOverlay settings, OsuConfigManager config, SessionStatics statics)
|
||||
{
|
||||
holdDelay = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay);
|
||||
holdDelay = config.GetBindable<double>(OsuSetting.UIHoldActivationDelay);
|
||||
loginDisplayed = statics.GetBindable<bool>(Static.LoginOverlayDisplayed);
|
||||
|
||||
if (host.CanExit)
|
||||
|
@ -63,11 +63,11 @@ namespace osu.Game.Screens.Play.HUD
|
||||
[Resolved]
|
||||
private OsuConfigManager config { get; set; }
|
||||
|
||||
private Bindable<float> activationDelay;
|
||||
private Bindable<double> activationDelay;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
activationDelay = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay);
|
||||
activationDelay = config.GetBindable<double>(OsuSetting.UIHoldActivationDelay);
|
||||
activationDelay.BindValueChanged(v =>
|
||||
{
|
||||
text.Text = v.NewValue > 0
|
||||
|
@ -3,12 +3,14 @@
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
@ -51,6 +53,8 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
private OsuColour colours { get; set; } = null!;
|
||||
|
||||
private double lastPlayAverage;
|
||||
private double lastPlayBeatmapOffset;
|
||||
private HitEventTimingDistributionGraph? lastPlayGraph;
|
||||
|
||||
private SettingsButton? useAverageButton;
|
||||
|
||||
@ -71,7 +75,7 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
Spacing = new Vector2(10),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new PlayerSliderBar<double>
|
||||
new OffsetSliderBar
|
||||
{
|
||||
KeyboardStep = 5,
|
||||
LabelText = BeatmapOffsetControlStrings.BeatmapOffset,
|
||||
@ -88,6 +92,28 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
};
|
||||
}
|
||||
|
||||
public class OffsetSliderBar : PlayerSliderBar<double>
|
||||
{
|
||||
protected override Drawable CreateControl() => new CustomSliderBar();
|
||||
|
||||
protected class CustomSliderBar : SliderBar
|
||||
{
|
||||
public override LocalisableString TooltipText =>
|
||||
Current.Value == 0
|
||||
? new TranslatableString("_", @"{0} ms", base.TooltipText)
|
||||
: new TranslatableString("_", @"{0} ms {1}", base.TooltipText, getEarlyLateText(Current.Value));
|
||||
|
||||
private LocalisableString getEarlyLateText(double value)
|
||||
{
|
||||
Debug.Assert(value != 0);
|
||||
|
||||
return value > 0
|
||||
? BeatmapOffsetControlStrings.HitObjectsAppearEarlier
|
||||
: BeatmapOffsetControlStrings.HitObjectsAppearLater;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -122,6 +148,12 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
|
||||
void updateOffset()
|
||||
{
|
||||
// the last play graph is relative to the offset at the point of the last play, so we need to factor that out.
|
||||
double adjustmentSinceLastPlay = lastPlayBeatmapOffset - Current.Value;
|
||||
|
||||
// Negative is applied here because the play graph is considering a hit offset, not track (as we currently use for clocks).
|
||||
lastPlayGraph?.UpdateOffset(-adjustmentSinceLastPlay);
|
||||
|
||||
// ensure the previous write has completed. ignoring performance concerns, if we don't do this, the async writes could be out of sequence.
|
||||
if (realmWriteTask?.IsCompleted == false)
|
||||
{
|
||||
@ -130,7 +162,9 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
}
|
||||
|
||||
if (useAverageButton != null)
|
||||
useAverageButton.Enabled.Value = !Precision.AlmostEquals(lastPlayAverage, -Current.Value, Current.Precision / 2);
|
||||
{
|
||||
useAverageButton.Enabled.Value = !Precision.AlmostEquals(lastPlayAverage, adjustmentSinceLastPlay, Current.Precision / 2);
|
||||
}
|
||||
|
||||
realmWriteTask = realm.WriteAsync(r =>
|
||||
{
|
||||
@ -187,10 +221,11 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
}
|
||||
|
||||
lastPlayAverage = average;
|
||||
lastPlayBeatmapOffset = Current.Value;
|
||||
|
||||
referenceScoreContainer.AddRange(new Drawable[]
|
||||
{
|
||||
new HitEventTimingDistributionGraph(hitEvents)
|
||||
lastPlayGraph = new HitEventTimingDistributionGraph(hitEvents)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 50,
|
||||
@ -199,7 +234,7 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
useAverageButton = new SettingsButton
|
||||
{
|
||||
Text = BeatmapOffsetControlStrings.CalibrateUsingLastPlay,
|
||||
Action = () => Current.Value = -lastPlayAverage
|
||||
Action = () => Current.Value = lastPlayBeatmapOffset - lastPlayAverage
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -15,13 +15,15 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
{
|
||||
public OsuSliderBar<T> Bar => (OsuSliderBar<T>)Control;
|
||||
|
||||
protected override Drawable CreateControl() => new SliderBar
|
||||
{
|
||||
RelativeSizeAxes = Axes.X
|
||||
};
|
||||
protected override Drawable CreateControl() => new SliderBar();
|
||||
|
||||
private class SliderBar : OsuSliderBar<T>
|
||||
protected class SliderBar : OsuSliderBar<T>
|
||||
{
|
||||
public SliderBar()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
|
@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Ranking.Statistics
|
||||
{
|
||||
@ -40,6 +41,9 @@ namespace osu.Game.Screens.Ranking.Statistics
|
||||
/// </summary>
|
||||
private const float axis_points = 5;
|
||||
|
||||
/// <summary>
|
||||
/// The currently displayed hit events.
|
||||
/// </summary>
|
||||
private readonly IReadOnlyList<HitEvent> hitEvents;
|
||||
|
||||
/// <summary>
|
||||
@ -51,121 +55,223 @@ namespace osu.Game.Screens.Ranking.Statistics
|
||||
this.hitEvents = hitEvents.Where(e => !(e.HitObject.HitWindows is HitWindows.EmptyHitWindows) && e.Result.IsHit()).ToList();
|
||||
}
|
||||
|
||||
private int[] bins;
|
||||
private double binSize;
|
||||
private double hitOffset;
|
||||
|
||||
private Bar[] barDrawables;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (hitEvents == null || hitEvents.Count == 0)
|
||||
return;
|
||||
|
||||
int[] bins = new int[total_timing_distribution_bins];
|
||||
bins = new int[total_timing_distribution_bins];
|
||||
|
||||
double binSize = Math.Ceiling(hitEvents.Max(e => Math.Abs(e.TimeOffset)) / timing_distribution_bins);
|
||||
binSize = Math.Ceiling(hitEvents.Max(e => Math.Abs(e.TimeOffset)) / timing_distribution_bins);
|
||||
|
||||
// Prevent div-by-0 by enforcing a minimum bin size
|
||||
binSize = Math.Max(1, binSize);
|
||||
|
||||
Scheduler.AddOnce(updateDisplay);
|
||||
}
|
||||
|
||||
public void UpdateOffset(double hitOffset)
|
||||
{
|
||||
this.hitOffset = hitOffset;
|
||||
Scheduler.AddOnce(updateDisplay);
|
||||
}
|
||||
|
||||
private void updateDisplay()
|
||||
{
|
||||
bool roundUp = true;
|
||||
|
||||
Array.Clear(bins, 0, bins.Length);
|
||||
|
||||
foreach (var e in hitEvents)
|
||||
{
|
||||
int binOffset = (int)Math.Round(e.TimeOffset / binSize, MidpointRounding.AwayFromZero);
|
||||
bins[timing_distribution_centre_bin_index + binOffset]++;
|
||||
double time = e.TimeOffset + hitOffset;
|
||||
|
||||
double binOffset = time / binSize;
|
||||
|
||||
// .NET's round midpoint handling doesn't provide a behaviour that works amazingly for display
|
||||
// purposes here. We want midpoint rounding to roughly distribute evenly to each adjacent bucket
|
||||
// so the easiest way is to cycle between downwards and upwards rounding as we process events.
|
||||
if (Math.Abs(binOffset - (int)binOffset) == 0.5)
|
||||
{
|
||||
binOffset = (int)binOffset + Math.Sign(binOffset) * (roundUp ? 1 : 0);
|
||||
roundUp = !roundUp;
|
||||
}
|
||||
|
||||
int index = timing_distribution_centre_bin_index + (int)Math.Round(binOffset, MidpointRounding.AwayFromZero);
|
||||
|
||||
// may be out of range when applying an offset. for such cases we can just drop the results.
|
||||
if (index >= 0 && index < bins.Length)
|
||||
bins[index]++;
|
||||
}
|
||||
|
||||
int maxCount = bins.Max();
|
||||
var bars = new Drawable[total_timing_distribution_bins];
|
||||
for (int i = 0; i < bars.Length; i++)
|
||||
bars[i] = new Bar { Height = Math.Max(0.05f, (float)bins[i] / maxCount) };
|
||||
|
||||
Container axisFlow;
|
||||
|
||||
InternalChild = new GridContainer
|
||||
if (barDrawables != null)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.8f,
|
||||
Content = new[]
|
||||
for (int i = 0; i < barDrawables.Length; i++)
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[] { bars }
|
||||
}
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
axisFlow = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y
|
||||
}
|
||||
},
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
barDrawables[i].UpdateOffset(bins[i]);
|
||||
}
|
||||
};
|
||||
|
||||
// Our axis will contain one centre element + 5 points on each side, each with a value depending on the number of bins * bin size.
|
||||
double maxValue = timing_distribution_bins * binSize;
|
||||
double axisValueStep = maxValue / axis_points;
|
||||
|
||||
axisFlow.Add(new OsuSpriteText
|
||||
}
|
||||
else
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = "0",
|
||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
|
||||
});
|
||||
int maxCount = bins.Max();
|
||||
barDrawables = new Bar[total_timing_distribution_bins];
|
||||
|
||||
for (int i = 1; i <= axis_points; i++)
|
||||
{
|
||||
double axisValue = i * axisValueStep;
|
||||
float position = (float)(axisValue / maxValue);
|
||||
float alpha = 1f - position * 0.8f;
|
||||
for (int i = 0; i < barDrawables.Length; i++)
|
||||
barDrawables[i] = new Bar(bins[i], maxCount, i == timing_distribution_centre_bin_index);
|
||||
|
||||
Container axisFlow;
|
||||
|
||||
const float axis_font_size = 12;
|
||||
|
||||
InternalChild = new GridContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.8f,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[] { barDrawables }
|
||||
}
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
axisFlow = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = axis_font_size,
|
||||
}
|
||||
},
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(),
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
}
|
||||
};
|
||||
|
||||
// Our axis will contain one centre element + 5 points on each side, each with a value depending on the number of bins * bin size.
|
||||
double maxValue = timing_distribution_bins * binSize;
|
||||
double axisValueStep = maxValue / axis_points;
|
||||
|
||||
axisFlow.Add(new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.X,
|
||||
X = -position / 2,
|
||||
Alpha = alpha,
|
||||
Text = axisValue.ToString("-0"),
|
||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
|
||||
Text = "0",
|
||||
Font = OsuFont.GetFont(size: axis_font_size, weight: FontWeight.SemiBold)
|
||||
});
|
||||
|
||||
axisFlow.Add(new OsuSpriteText
|
||||
for (int i = 1; i <= axis_points; i++)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.X,
|
||||
X = position / 2,
|
||||
Alpha = alpha,
|
||||
Text = axisValue.ToString("+0"),
|
||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
|
||||
});
|
||||
double axisValue = i * axisValueStep;
|
||||
float position = (float)(axisValue / maxValue);
|
||||
float alpha = 1f - position * 0.8f;
|
||||
|
||||
axisFlow.Add(new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.X,
|
||||
X = -position / 2,
|
||||
Alpha = alpha,
|
||||
Text = axisValue.ToString("-0"),
|
||||
Font = OsuFont.GetFont(size: axis_font_size, weight: FontWeight.SemiBold)
|
||||
});
|
||||
|
||||
axisFlow.Add(new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.X,
|
||||
X = position / 2,
|
||||
Alpha = alpha,
|
||||
Text = axisValue.ToString("+0"),
|
||||
Font = OsuFont.GetFont(size: axis_font_size, weight: FontWeight.SemiBold)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Bar : CompositeDrawable
|
||||
{
|
||||
public Bar()
|
||||
private readonly float value;
|
||||
private readonly float maxValue;
|
||||
|
||||
private readonly Circle boxOriginal;
|
||||
private Circle boxAdjustment;
|
||||
|
||||
private const float minimum_height = 0.05f;
|
||||
|
||||
public Bar(float value, float maxValue, bool isCentre)
|
||||
{
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Origin = Anchor.BottomCentre;
|
||||
this.value = value;
|
||||
this.maxValue = maxValue;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
|
||||
InternalChild = new Circle
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4Extensions.FromHex("#66FFCC")
|
||||
boxOriginal = new Circle
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Colour = isCentre ? Color4.White : Color4Extensions.FromHex("#66FFCC"),
|
||||
Height = minimum_height,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private const double duration = 300;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
float height = Math.Clamp(value / maxValue, minimum_height, 1);
|
||||
|
||||
if (height > minimum_height)
|
||||
boxOriginal.ResizeHeightTo(height, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
public void UpdateOffset(float adjustment)
|
||||
{
|
||||
bool hasAdjustment = adjustment != value && adjustment / maxValue >= minimum_height;
|
||||
|
||||
if (boxAdjustment == null)
|
||||
{
|
||||
if (!hasAdjustment)
|
||||
return;
|
||||
|
||||
AddInternal(boxAdjustment = new Circle
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Colour = Color4.Yellow,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0.6f,
|
||||
Height = 0,
|
||||
});
|
||||
}
|
||||
|
||||
boxAdjustment.ResizeHeightTo(Math.Clamp(adjustment / maxValue, minimum_height, 1), duration, Easing.OutQuint);
|
||||
boxAdjustment.FadeTo(!hasAdjustment ? 0 : 1, duration, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,8 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="10.9.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.223.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.211.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.304.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.304.0" />
|
||||
<PackageReference Include="Sentry" Version="3.14.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.30.1" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
|
@ -61,8 +61,8 @@
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.223.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.211.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.304.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.304.0" />
|
||||
</ItemGroup>
|
||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
|
||||
<PropertyGroup>
|
||||
@ -84,7 +84,7 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="5.0.14" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.223.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2022.304.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.30.1" />
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
|
Loading…
Reference in New Issue
Block a user